Given two structs where some fields might be null on either one, what is the most elegant way of merging them? (taking one side if both have a non-nulled field?)
I am unsure how to do this without comparing each field.
Given two structs where some fields might be null on either one, what is the most elegant way of merging them? (taking one side if both have a non-nulled field?)
I am unsure how to do this without comparing each field.
If you don't care the cost too much.I have an very inefficient solution. Using the json marshal and unmarshal with omitempty tag. Hope it can help you somewhere.
package main
import (
    "fmt"
    "encoding/json"
)
type myStruct struct{
    Id int      `json:"id,omitempty"`
    Name string `json:"name,omitempty"`
    Sex bool `json:"sex,omitempty"`
    Age int `json:"age,omitempty"`
    Addr string `json:"addr,omitempty"`
}
func MergeStruct(to interface{},from interface{}) error{
    byte1,err := json.Marshal(to)
    if err != nil {
        return err
    }
    byte2,err := json.Marshal(from)
    if err != nil {
        return err
    }
    map1 := make(map[string]interface{})
    err = json.Unmarshal(byte1,&map1)
    if err != nil {
        return err
    }
    map2 := make(map[string]interface{})
    err = json.Unmarshal(byte2,&map2)
    if err != nil {
        return err
    }
    for k,v := range map2{
        map1[k] = v
    }
    byteDest,err := json.Marshal(map1)
    if err != nil {
        return err
    }
    err = json.Unmarshal(byteDest,to)
    return err
}
func main() {
    st1 := myStruct{
        Id:1,
        Name:"saky1",
        Addr:"addr1",
    }
    st2 := myStruct{
        Id:2,
        Name:"saky2",
        Age:20,
    }
    fmt.Println("befor merge: ",st1)
    MergeStruct(&st1,&st2)
    fmt.Println("after merge: ",st1)
}
Output:
befor merge:  {1 saky1 false 0 addr1}
after merge:  {2 saky2 false 20 addr1}
    You'd also need to ask yourself the following questions:
The first one isn't really a problem in most cases because usually the result will be nil then. The second one isn't really a problem in most cases because usually you'll define some precedence (i.e. first argument wins over second argument). 
The third one is a bit trickier. You can define to take whichever is non-zero.
Nesting is also a bit tricky. You might want to "deep merge" some structs or just superficially merge some structs.
Anyway, you can do this with reflect but it's going to be tricky (unless somebody has already done it). With some 5minutes hacking you can get this:
func f(a,b interface{}) {
    ra := reflect.ValueOf(a).Elem()
    rb := reflect.ValueOf(b).Elem()
    numFields := ra.NumField()
    for i := 0; i < numFields; i++ {
        field_a := ra.Field(i)
        field_b := rb.Field(i)
        switch field_a.Kind() {
        case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
            if field_a.IsNil() {
                field_a.Set(field_b)
            }
        }
    }
}
but this is FAR from complete and it'll only work with exported fields because accessing unexported fields isn't too convenient with reflect and requires more quirks to do it. It also doesn't recurse but you can of course recurse if you detect nested structs etc. 
However, it's probably better if you just write a manual merge function for your structs.