L'éditeur php Xigua est là pour vous présenter une méthode d'utilisation des valeurs dans d'autres structures "parties" pour écraser les champs de structure. En programmation, nous avons souvent besoin de mettre à jour les valeurs des champs de structure en fonction de différentes situations. Dans ce cas, nous pouvons écraser les champs de la structure cible par des valeurs d'autres structures. Cette méthode est très pratique et peut améliorer la lisibilité et la flexibilité du code. Ensuite, je détaillerai comment utiliser cette technique pour simplifier votre code et le rendre plus efficace.
Je suis nouveau sur Go et j'essaie de créer une API CRUD. Veuillez me pardonner que l'approche POO dans Go n'est peut-être pas intelligente. J'ai une structure que je souhaite mettre à jour partiellement via le point de terminaison PATCH.
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"` }
J'ai défini une deuxième structure qui contient une propriété pouvant être mise à jour pour un livre.
type PatchBookDto struct { Author *uuid.UUID Title *string IsPublic *bool }
Dans les deux structures, j'utilise (peut-être en abusant ?) des attributs de pointeur pour simuler des paramètres facultatifs. Ce que je veux réaliser, c'est écraser un livre avec une propriété donnée dans PatchBookDto. Voici ce que j'ai essayé jusqu'à présent :
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) } }
Lorsque j'ai testé cela, j'ai eu l'erreur reflect.Value.Convert: value of type *string Cannot be conversion to type string
.
Est-ce que quelqu'un sait ce que je peux améliorer ici pour obtenir ce dont j'ai besoin ?
On dirait que vous avez l'intention de mettre la ligne de panique dans le bloc if dtoField.Type.Kind() ==reflect.Ptr
else.
Une autre façon consiste à utiliser un pointeur indirect, puis à définir la valeur.
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) } }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!