更新方法不更新零值

Update method does not update zero value

原题

在 GORM 中使用 Update 方法时,新数据不会被保存。即,我想将 booltrue 设置为 false,但即使在 Update 方法之后它仍然是真实的。

在方法的描述中有一个警告:“警告当使用结构更新时,GORM 将不会更新具有零值的字段”

因为我正在使用一个结构来更新并且 falsebool 的零值,这似乎是预期的行为,但我看不出有任何理由这样做以及如何克服这个。

func UpdateData(c *fiber.Ctx) error {
    db := database.DBConn

    data := new([]entities.Data)

    if err := c.BodyParser(&data); err != nil {
        return err
    }

    db.Update(&data)
    return c.JSON(data)
}

解决方案总结

首先,按照建议,我在实例化结构时省略了 new 关键字。然后,我使用辅助函数(来自 here)将结构转换为映射,同时将 json 别名保留为键:

// StructToMap Converts a struct to a map while maintaining the json alias as keys
func StructToMap(obj interface{}) (newMap map[string]interface{}, err error) {
    data, err := json.Marshal(obj)

    if err != nil {
        return
    }

    err = json.Unmarshal(data, &newMap) // Convert to a map
    return
}

然后我循环遍历数据切片中的每个元素,以便对其进行转换并逐一更新:

func UpdateData(c *fiber.Ctx) error {
    db := database.DBConn

    data := []entities.Dard{}

    if err := c.BodyParser(&data); err != nil {
        return err
    }

    for _, record := range data {
        mappedData, _ := StructToMap(record)
        db.Model(&entities.Data{}).Update(mappedData)
    }

    return c.JSON(data)
}

*此示例中的错误处理明显减少。

来自官方doc

NOTE When update with struct, GORM will only update non-zero fields, you might want to use map to update attributes or use Select to specify fields to update

因此也使用 map[string]interface{} 来更新 non-zero 字段。示例:

db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})

因为你已经有了结构,你可以将 struct 转换成 map[string]interface{} (See details about conversion) 然后更新。另一种方法是将字段类型更改为指针。