Selectively copy go struct fields

Selectively copy go struct fields



I wanted a way to selectively copy Go fields from one struct to another. This allows me to update data from one struct to another without changing certain information. Here's the solution I came up with. It depends on setting a tag field of "update". Would appreciate any feedback for making this more robust or better or maybe why this is just a bad idea to begin with.


import (
"errors"
"fmt"
"reflect"
)

func UpdateStruct(src, dst interface) error
if reflect.TypeOf(src) != reflect.TypeOf(dst)
return errors.New("structs not of same type")


if reflect.ValueOf(src).Kind() != reflect.Ptr
return errors.New("arguments must be pointers")


srcVal := reflect.ValueOf(src).Elem()
srcType := srcVal.Type()

dstVal := reflect.ValueOf(dst).Elem()

for i := 0; i < srcVal.NumField(); i++
s := srcType.Field(i)
if tag := s.Tag.Get("update"); tag == ""
continue

fieldName := srcType.Field(i).Name
d := dstVal.FieldByName(fieldName)
if d.IsValid()
if d.CanSet()
d.Set(srcVal.Field(i))
else
return fmt.Errorf("cannot set field: %s", fieldName)

else
return fmt.Errorf("invalid field: %s", fieldName)



return nil



example struct:


type Tester struct
ID string
Name string `update:"true"`
Date time.Time `update:"true"`
Decimal float64 `update:"true"`
Number int `update:"true"`
CaseID uuid.UUID `update:"true"`






This implementation, is also supposed to work when there are structs within structs correct? it fails there. There is a way of doing this using github.com/fatih/structs.

– whitespace
Sep 12 '18 at 4:32






@whitespace OP's code works with the type in question and this type has nested structs.

– ThunderCat
Sep 12 '18 at 5:03






@ThunderCat, I think you misunderstood my concern. I am not talking about first level copy. I think, question is still valid for structs which have structs inside them, where the nested structs have some fields I would want to copy and some fields I don't want to copy.

– whitespace
Sep 12 '18 at 5:08






@whitespace The OP may want to selectively copy within nested structs, but the question does not ask for that feature, nor is that feature needed in all possible uses of the function. Sebastian, do you want to selectively copy within nested structs or do you want to copy nested selects wholesale?

– ThunderCat
Sep 12 '18 at 5:16







@whitespace selectively copying fields within nested structs is beyond the scope of my original question. Maybe someone will have that question down the road however. It could add to the robustness of this code or be part of another question.

– Sebastian
Sep 12 '18 at 13:21




1 Answer
1



The code will panic if the arguments are not pointers to structs. There'a check for a pointer, but not for a pointer to a struct. Add this code:


srcVal := reflect.ValueOf(src).Elem()
if srcVal.Kind() != reflect.Struct
return errors.New("arguments must be pointers to structs")



Because the function is starting with a pointer to a struct, the fields are guaranteed to be settable. Because the field values are obtained from a valid struct value, the fields are guaranteed to be valid. Fields can be accessed by index in addition to by name. Given this, the inner loop can be simplified to:


for i := 0; i < srcVal.NumField(); i++
s := srcType.Field(i)
if tag := s.Tag.Get("update"); tag == ""
continue

dstVal.Field(i).Set(srcVal.Field(i))



Run it on the playground



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

ャフサォクコ ケウ,コ,ワ メ,ロスョノ゙,クネ,フムカヤヲニ,エコ゚ツ ウイオン゙ケワサネォキモュキォウイノンコチ゚メヌナイゥフュ,カヒウネェ ネ,ホノケ,ムュキ ッボーミュハ,チ ツス ィ メウイマヤ,゙ウチ ヅ ロ,ォジヌェ ャヌット ェ,マャ,チナエヒネソキツテ トホヲヲミーァ

How do I collapse sections of code in Visual Studio Code for Windows?