You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go开发如何实现仅更新数据库中JSON请求传入的指定字段而非全部

问题根因

Go的基础数据类型存在默认零值,string类型的零值为空字符串。当JSON中未传入对应字段时,json.Unmarshal会将模型的对应字段赋值为零值,你当前写死所有字段的UPDATE语句会直接将这些零值写入数据库,导致原有数据被覆盖。同时你也无法通过空字符串判断是用户主动传空还是未传字段。

解决方案

步骤1:修改User模型,将字段改为指针类型

指针类型的零值为nil,JSON反序列化时未传入的字段会保持nil值,传入的字段(包括主动传空字符串的情况)会被赋值为非nil的指针,以此可以准确区分用户是否提交了该字段:

type User struct {
    ID       *uint64 `json:"id,omitempty"`
    Name     *string `json:"name,omitempty"`
    CPF      *string `json:"cpf,omitempty"`
    Email    *string `json:"email,omitempty"`
    Password *string `json:"password,omitempty"`
    City     *string `json:"city,omitempty"`
    State    *string `json:"state,omitempty"`
}

步骤2:重构Repository层的更新方法,动态拼接SQL

不再使用写死全字段的UPDATE语句,而是根据User模型中非nil的字段动态构建要更新的字段列表和参数:

import (
    "fmt"
    "strings"
)

func (repository Users) UpdateUserInfo(userID uint64, user models.User) error {
    var setClauses []string
    var args []interface{}

    // 仅收集用户提交的非空字段
    if user.Name != nil {
        setClauses = append(setClauses, "name = ?")
        args = append(args, *user.Name)
    }
    if user.CPF != nil {
        setClauses = append(setClauses, "cpf = ?")
        args = append(args, *user.CPF)
    }
    if user.Email != nil {
        setClauses = append(setClauses, "email = ?")
        args = append(args, *user.Email)
    }
    if user.Password != nil {
        setClauses = append(setClauses, "password = ?")
        args = append(args, *user.Password)
    }
    if user.City != nil {
        setClauses = append(setClauses, "city = ?")
        args = append(args, *user.City)
    }
    if user.State != nil {
        setClauses = append(setClauses, "state = ?")
        args = append(args, *user.State)
    }

    // 无更新字段直接返回,避免执行无效SQL
    if len(setClauses) == 0 {
        return nil
    }

    // 拼接最终执行的SQL
    updateSql := fmt.Sprintf("UPDATE user SET %s WHERE id = ?", strings.Join(setClauses, ", "))
    args = append(args, userID)

    stmt, err := repository.db.Prepare(updateSql)
    if err != nil {
        return err
    }
    defer stmt.Close()

    _, err = stmt.Exec(args...)
    return err
}

优化方案

如果项目允许引入ORM框架,可直接使用GORM这类框架的Updates方法,天然支持仅更新非零值字段,不需要手动拼接SQL:

// GORM示例代码,仅作参考
func (repository Users) UpdateUserInfo(userID uint64, user models.User) error {
    return repository.db.Model(&User{}).Where("id = ?", userID).Updates(user).Error
}

内容的提问来源于stack exchange,提问作者Leonardo Henrique

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 12:06:05