mergo icon indicating copy to clipboard operation
mergo copied to clipboard

Transformers: How to access underlying datatype

Open vasu-dasari opened this issue 1 year ago • 0 comments

Hi,

We are trying to do a custom merge on slices in our project. For simplicity I have used IntSlice(a custom type of slice of ints) in this example. The problem I see is, when I type case src/dst in the transformer function, it is coming out as empty [], although those variables do contain right elements.

My question is how to have the variables srcSlice and dstSlice cast to the type IntSlice appropriately.

Code in go playground

type IntSlice []int16

type MySubStruct struct {
    SubIntSlice IntSlice
}
type MyStruct struct {
    IntSlice    IntSlice
    MySubStruct MySubStruct
}

func (t IntSlice) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
    if typ == reflect.TypeOf(IntSlice{}) {
        return func(dst, src reflect.Value) error {
            // I would like to do a custom merge like this
            dstSlice, _ := reflect.ValueOf(dst).Interface().(IntSlice)
            srcSlice, _ := reflect.ValueOf(src).Interface().([]int16)

            for _, s := range srcSlice {
                dstSlice = append(dstSlice, s)
            }

            // Unfortunately all srcSlice and dstSlice are cast as empty slices even though the src and dst
            // fields are indeed valid slices as displayed via %v in following statement
            log.Printf("transformer: srcSlice %++v(%d), src %++v", srcSlice, len(srcSlice), src)
            return nil
        }
    }
    return nil
}

func mergeSliceTest() {
    dst := MyStruct{
        IntSlice: IntSlice{1, 2, 3},
        MySubStruct: MySubStruct{
            SubIntSlice: IntSlice{4, 5, 6},
        },
    }
    src := MyStruct{
        IntSlice: IntSlice{10, 20, 30},
        MySubStruct: MySubStruct{
            SubIntSlice: IntSlice{40, 50, 60},
        },
    }
    if err := mergo.Merge(&dst, src, mergo.WithTransformers(IntSlice{})); err != nil {
        log.Printf("err %v", err)
        return
    }
    log.Printf("result: dst %v", dst)
}

vasu-dasari avatar Jul 30 '22 12:07 vasu-dasari