如何让Go-Gorm填充-:all标记的忽略字段存储查询计算结果
Gorm计算字段填充与数据库字段控制问题解决
场景说明
我使用Go-Gorm定义了如下模型结构体:
type Inventory struct { ID int `gorm:"primaryKey;notNull" json:"id"` Qty uint `json:"qty"` In *int `gorm:"-:all" json:"in"` Out *int `gorm:"-:all" json:"out"` }
其中In和Out是计算字段,希望通过以下SQL逻辑生成值:
IFNULL(SUM(IF(qty > 0, qty, 0)),0) AS in
IFNULL(SUM(IF(qty < 0, qty, 0)),0) AS out
但使用-:all标签后,Gorm完全忽略这两个字段,无法将SQL计算结果填充到结构体中。当前临时方案是改用<-:false标签,但会导致数据库中生成无意义的空列,不符合需求。
解决方案
正确的标签设置与查询方式
将In和Out字段的标签改为gorm:"-",这个标签会让Gorm在迁移、创建、更新、默认查询时都忽略这些字段,但允许通过Scan方法将查询结果映射到结构体:
修改后的结构体:
type Inventory struct { ID int `gorm:"primaryKey;notNull" json:"id"` Qty uint `json:"qty"` In *int `gorm:"-" json:"in"` Out *int `gorm:"-" json:"out"` }
自定义查询填充计算字段
查询时通过Select方法明确指定需要查询的字段,包括计算后的in和out,再通过Scan将结果映射到结构体:
var inventory Inventory db.Model(&Inventory{}). Select("id, qty, IFNULL(SUM(IF(qty > 0, qty, 0)),0) AS in, IFNULL(SUM(IF(qty < 0, qty, 0)),0) AS out"). Scan(&inventory)
注意:SQL中
AS后的别名要与结构体字段名(In/Out)对应,Gorm会自动处理大小写映射(数据库不区分大小写)。如果需要更精确的映射,可以给结构体字段添加gorm:"column:in"标签,配合gorm:"-"时仅在Scan映射时生效。
批量查询场景
如果是批量查询,同样适用,只需将Scan的目标改为切片:
var inventories []Inventory db.Model(&Inventory{}). Select("id, qty, IFNULL(SUM(IF(qty > 0, qty, 0)),0) AS in, IFNULL(SUM(IF(qty < 0, qty, 0)),0) AS out"). Scan(&inventories)
方案优势
- 完全避免在数据库中创建无用的
in/out列,符合数据库设计规范 - 精准控制Gorm对字段的处理逻辑:既不参与数据库操作,又能接收自定义查询的计算结果
内容的提问来源于stack exchange,提问作者Bens
相关产品推荐
相关产品推荐

