php editor Xigua is here to introduce to you a method about using values in other "part" structures to overwrite structure fields. In programming, we often need to update the values of structure fields according to different situations. In this case, we can overwrite the fields in the target structure with values from other structures. This method is very practical and can improve the readability and flexibility of the code. Next, I'll detail how to use this technique to simplify your code and make it more efficient.
I am new to Go and trying to create a CRUD API. Please forgive me that the OOP approach in Go may not be smart. I have a structure that I want to partially update via the PATCH endpoint.
type Book struct { Id uuid.UUID `json:"id"` Author uuid.UUID `json:"author"` Title string `json:"title"` IsPublic bool `json:"isPublic"` CreatedAt time.Time `json:"createdAt"` UpdatedAt *time.Time `json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` }
I have defined a second structure that contains an updateable property for a book.
type PatchBookDto struct { Author *uuid.UUID Title *string IsPublic *bool }
In both structures, I'm using (possibly abusing?) pointer attributes to simulate optional parameters. What I want to achieve is to overwrite a book with any given property in PatchBookDto. Here's what I've tried so far:
var book models.Book // Is taken from an array of books var dto dtos.PatchBookDto if err := c.BindJSON(&dto); err != nil { // Abort } dtoTypeInfo := reflect.TypeOf(&dto).Elem() for i := 0; i < dtoTypeInfo.NumField(); i++ { dtoField := dtoTypeInfo.Field(i) bookField := reflect.ValueOf(&book).Elem().FieldByName(dtoField.Name) if bookField.IsValid() && bookField.CanSet() { dtoValue := reflect.ValueOf(dto).Field(i) if dtoValue.Interface() == reflect.Zero(dtoValue.Type()).Interface() { continue } if dtoField.Type.Kind() == reflect.Ptr { if dtoValue.Elem().Type().AssignableTo(bookField.Type()) { bookField.Set(dtoValue.Elem()) } else { // Abort } } convertedValue := dtoValue.Convert(bookField.Type()) bookField.Set(convertedValue) } }
When I test this, I get the reflect.Value.Convert: value of type *string Cannot be converted to type string
error.
Does anyone know what I can improve here to get what I need?
Looks like you intended to put the panic line in the else block of if dtoField.Type.Kind() ==reflect.Ptr
.
Another way is to use an indirect pointer and then set the value.
for i := 0; i < dtoTypeInfo.NumField(); i++ { dtoField := dtoTypeInfo.Field(i) bookField := reflect.ValueOf(&book).Elem().FieldByName(dtoField.Name) if bookField.IsValid() && bookField.CanSet() { dtoValue := reflect.ValueOf(dto).Field(i) if dtoValue.Interface() == reflect.Zero(dtoValue.Type()).Interface() { continue } dtoValue = reflect.Indirect(dtoValue) convertedValue := dtoValue.Convert(bookField.Type()) bookField.Set(convertedValue) } }
The above is the detailed content of Override structure fields with values from other 'part' structures. For more information, please follow other related articles on the PHP Chinese website!