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

Golang中Gorm NOT NULL约束未拦截零值存入数据库的问题

为何GORM结构体的not null约束未触发报错?

问题相关代码

结构体定义

type Task struct {
    gorm.Model
    Id         int       `json:"id" gorm:"primaryKey;AUTO_INCREMENT"`
    UserId     int       `json:"user_id" gorm:"Index;not null" validate:"required"`
    TaskId     int       `json:"task_id" gorm:"Index;not null" validate:"required"`
    JobId      int       `json:"job_id" gorm:"not null" validate:"required"`
    Latitude   float64   `json:"latitude" gorm:"not null" validate:"required"`
    Longitude  float64   `json:"longitude" gorm:"not null" validate:"required"`
    StartAt    time.Time `json:"start_at"`
    EndAt      time.Time `json:"end_at"`
    CreatedAt  time.Time
    UpdatedAt  time.Time
}

请求体与处理函数

请求体:

{   
    "user_id": 1,
    "location":[5748.5445, 89790.454],
    "latitude": 89790.454,
    "longitude": 5748.5445,
    "startAt":  "2030-10-30T10:58:00.000Z",
    "endAt": "2031-10-30T10:58:00.000Z"
}

处理函数:

func CreateTask(c *fiber.Ctx) error {
    var opentask models.JobOpenTask
    
    if err := c.BodyParser(&opentask); err != nil {
        return c.Status(400).JSON(err.Error())
    }
    
    db.DB.Db.Create(&opentask)
    return c.Status(200).JSON("OK")
}

疑问

运行代码时,记录能成功存入数据库,但预期结构体中设置的not null约束会触发报错,为何无报错?


原因分析

  • gorm:"not null"只作用于表结构迁移
    这个标签是给GORM的自动迁移功能用的,只有当你调用AutoMigrate创建/更新表结构时,才会给数据库字段加上NOT NULL约束。如果你的表没经过正确迁移,或者迁移后约束没生效,数据库本身就不会拦截空值插入。

  • 未捕获GORM的创建错误
    你调用Create方法后没检查返回的错误。就算数据库真的有NOT NULL约束,插入违规数据时GORM会返回错误,但你没处理这个错误,程序自然不会抛出异常,反而返回200。正确写法应该捕获Create的错误:

    if err := db.DB.Db.Create(&opentask).Error; err != nil {
        return c.Status(500).JSON(err.Error())
    }
    
  • Go基础类型零值不等于数据库NULL
    结构体里的TaskId、JobId是int类型,Go中int的零值是0。请求体没传这两个字段,BodyParser会把它们设为0。而数据库的NOT NULL约束只是不允许字段为NULL,0是合法的非NULL值,所以插入会成功——你混淆了“零值”和“NULL”的概念。

  • validate:"required"标签没生效
    这个标签属于第三方校验库(比如go-playground/validator),GORM不会自动处理。你需要手动调用校验逻辑,在BodyParser之后添加:

    validate := validator.New()
    if err := validate.Struct(&opentask); err != nil {
        return c.Status(400).JSON(err.Error())
    }
    

内容的提问来源于stack exchange,提问作者Kingsley Simon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 03:00:51