Golang Merge Struct Just Like Javascript Merge Object with Spread Syntax

February 11, 2023tip slipsgolang

Did you work with Javascript before but now working with Golang and miss the idea of easily merging object by simply using spread operator or JS Object.assign? In JS we can do simply { ...oldObject, ...newObjectValue }. We can't do that in Go but I made a util func to achieve the same idea to it

Here is the code I made to do just like what you've been craving it

import "reflect"

// ex:
// a := User { Id: 0, Name: "Yuza", Age: 20 }
// b := UserBody { Name: "Yakuza" }
// result -- a = User{ Id: 0, Name: "Yakuza", Age: 20 }
func MergeInPlaceStructWithPartialStruct(obj, partialObj interface{}) {
    objValue := reflect.ValueOf(obj).Elem()
    partialObjValue := reflect.ValueOf(partialObj)

    for i := 0; i < objValue.NumField(); i++ {
        objField := objValue.Field(i)
        if !objField.CanSet() {
            continue
        }

        partialObjField := partialObjValue.FieldByName(objValue.Type().Field(i).Name)
        if partialObjField.IsValid() {
            objField.Set(partialObjField)
        }
    }
}

Yes, it uses reflect ffs but who does not use it when they work with Go. And here is how to use the function above

type Photo struct {
    Id         string
    UserId     string
    Title      string
    Caption    string
    PhotoUrl   string
}

type PhotoBody struct {
    Title    string
    Caption  string
    PhotoUrl string
}

func SomeRequestHandler() {
    photoData := Photo{ Id: "69", UserId: "420" }
    restOfPhotoData := PhotoBody{ Title: "a sexy worm dancing", Caption: "A worm dancing after taking weed", PhotoUrl: "imgur.com" } 
    MergeInPlaceStructWithPartialStruct(&photoData, restOfPhotoData)

    fmt.Printf("%+v\n", photoData) // { Id:69 UserId:420 Title:a sexy worm dancing Caption:A worm dancing after taking weed PhotoUrl:imgur.com }
}