Go语言 用其他“部分”结构的值覆盖结构字段

uqdfh47h  于 2024-01-04  发布在  Go
关注(0)|答案(1)|浏览(145)

我是Go的新手,我正在尝试创建一个CRUD API。请原谅Go中的OOP方法,它可能并不聪明。我有一个结构,我想通过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"`
}

字符串
我已经为一本书定义了第二个具有可更新属性的结构体。

type PatchBookDto struct {
  Author   *uuid.UUID
  Title    *string
  IsPublic *bool
}


在这两个结构体中,我都使用(可能滥用?)指针属性来模仿可选参数。我想实现的是用PatchBookDto中的任何给定属性覆盖一本书。这是我目前为止的尝试:

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)
    }
}


当我测试这个时,我得到一个reflect.Value.Convert: value of type *string cannot be converted to type string错误。
有人知道我可以在这里改进什么来得到我需要的吗?

yzxexxkh

yzxexxkh1#

看起来你打算把恐慌行放在if dtoField.Type.Kind() == reflect.Ptr的else块中。
另一种方法是间接指针,然后设置值。

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)
    }
}

字符串

相关问题