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
相关产品推荐
相关产品推荐

