mitchellh / copystructure

Go (golang) library for deep copying values in Go.

Home Page:https://gist.github.com/mitchellh/90029601268e59a29e64e55bab1c5bdc

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Custom CopierFuncs via CopyConfig not working

terrabitz opened this issue · comments

Environment

  • Go Version: 1.14.2
  • copystructure version: v1.0.0
  • OS: Linux x64

The Problem

In order to support some complex structs with private members, I need to use a custom copier to copy the values over. Attempting to do this by setting Config.Copiers doesn't appear to work. For example, take the following test:

package cmp

import (
	"reflect"
	"testing"

	"github.com/mitchellh/copystructure"
)

type MyStruct struct {
	S string
}

func CopyMyStruct(i interface{}) (interface{}, error) {
	return MyStruct{
		S: "FOO",
	}, nil
}

// This doesn't work
func Test_CustomCopierConfig(t *testing.T) {
	copyConfig := copystructure.Config{
		Copiers: map[reflect.Type]copystructure.CopierFunc{
			reflect.TypeOf(MyStruct{}): CopyMyStruct,
		},
	}

	o1 := MyStruct{
		S: "BAR",
	}

	cp, _ := copyConfig.Copy(o1)
	o2 := cp.(MyStruct)

	if o2.S != "FOO" {
		t.Errorf("CopyMyStruct() expected 'FOO', got '%s'", o2.S)
	}
}

// This works
func Test_CustomCopierGlobal(t *testing.T) {
	copystructure.Copiers[reflect.TypeOf(MyStruct{})] = CopyMyStruct

	o1 := MyStruct{
		S: "BAR",
	}

	cp, _ := copystructure.Copy(o1)
	o2 := cp.(MyStruct)

	if o2.S != "FOO" {
		t.Errorf("CopyMyStruct() expected 'FOO', got '%s'", o2.S)
	}
}

While the test which sets the global Copiers variable works just fine, the one which uses a specific Config does not.

Recommended Solution

My best guess is that the problem resides here: https://github.com/mitchellh/copystructure/blob/master/copystructure.go#L359. It appears that the global Copiers variable is getting used regardless of the value of Config.Copiers. The walker.Struct function signature should probably be updated to accept a Copiers object, and then the correct Copiers can be passed down.

It might also be helpful to document the expected workflow for creating custom copier functions. If the expectation is that the global will always be used, then it would be helpful to document that.