Home > Article > Backend Development > What is the correct way to conditionally assign multiple properties to a struct
I am developing a parser function for be's graphql query that I wrote in go. In the parser, I have user data that I want to update, using an input value that contains multiple possible update properties.
In javascript this can be done quickly via destructuring (pseudo):
const mergedobj = {...oldprops, ...newprops}
Currently, my parser function looks like this (using gqlgen as the graphql go parser):
func (r *mutationResolver) ModifyUser(ctx context.Context, input *model.ModifyUserInput) (*model.User, error) { id := input.ID us, ok := r.Resolver.UserStore[id] if !ok { return nil, fmt.Errorf("not found") } if input.FirstName != nil { us.FirstName = *input.FirstName } if input.LastName != nil { us.LastName = *input.LastName } if input.ProfileImage != nil { us.ProfileImage = input.ProfileImage } if input.Password != nil { us.Password = *input.Password } if input.Email != nil { us.Email = *input.Email } if input.InTomorrow != nil { us.InTomorrow = input.InTomorrow } if input.DefaultDaysIn != nil { us.DefaultDaysIn = input.DefaultDaysIn } r.Resolver.UserStore[id] = us return &us, nil }
This feels very simple. Does it make sense to iterate over the struct keys in this case? Or is there another pattern I'm missing?
Use functions to reduce boilerplate:
func mergef[t any](a, b *t) { if b != nil { *a = *b } } ... mergef(&us.firstname, input.firstname) mergef(&us.lastname, input.lastname) ...
Use the reflection package to reduce more boilerplate:
// merge sets fields in struct pointed to by d to // dereferenced fields in struct pointed to by s. // // argument s must point to a struct with pointer type // fields. // argument d must point to a struct with fields that // correspond to the fields in s: there must be a field // in d with the same name as a field in s; the type of // the field in s must be a pointer to the type of the field // in d. func merge(d, s any) { sv := reflect.valueof(s).elem() dv := reflect.valueof(d).elem() for i := 0; i < sv.numfield(); i++ { sf := sv.field(i) if sf.isnil() { continue } df := dv.fieldbyname(sv.type().field(i).name) df.set(sf.elem()) } }
Use a function like this:
merge(us, input)
The above is the detailed content of What is the correct way to conditionally assign multiple properties to a struct. For more information, please follow other related articles on the PHP Chinese website!