
gorm 本身不内置 decimal 类型,但可通过第三方库 shopspring/decimal 结合 sql 标签实现高精度小数(如 `decimal(20,8)`)的定义与操作,适用于金融、计费等对精度敏感的场景。
在数据库建模中,尤其是处理货币、财务结算等需严格保证精度的业务时,浮点类型(如 float64)极易引发舍入误差。而 SQL 标准中的 DECIMAL(p,s)(如 DECIMAL(20,8))可确保定点数的精确存储与计算。GORM 作为 Go 语言主流 ORM 框架,原生 Struct 标签中并不提供 decimal 类型字段支持,但它完全兼容自定义类型——只要该类型实现了 GORM 所需的接口(如 driver.Valuer 和 sql.Scanner)。
推荐方案是集成 shopspring/decimal,这是一个被广泛采用、高精度、无浮点误差的 Go Decimal 库。它天然满足 GORM 的序列化要求,只需配合 sql 标签指定数据库列类型即可:
import "github.com/shopspring/decimal"
type Order struct {
ID uint `gorm:"primaryKey"`
Amount decimal.Decimal `json:"amount" sql:"type:decimal(20,8);not null"`
}✅ 关键说明:
- sql:"type:decimal(20,8)" 告诉 GORM 在自动迁移(AutoMigrate)时创建 DECIMAL(20,8) 列;
- decimal.Decimal 会自动处理数据库 []byte ↔ decimal.Decimal 的双向转换(得益于其已实现 Valuer/Scanner);
- 不要使用 float32 或 float64 替代,即便加了 sql:"type:decimal" 标签,Go 层仍会以二进制浮点运算,丧失精度保障。
⚠️ 注意事项:
- 确保数据库驱动(如 mysql 或 postgres)支持 DECIMAL 类型(主流驱动均支持);
- 迁移前建议显式启用 gorm.Config{SkipDefaultTransaction: true} 避免事务干扰;
- 若需 JSON 序列化,shopspring/decimal 默认输出字符串(如 "123.45"),符合 API 安全规范,无需额外配置。
综上,GORM + shopspring/decimal 是 Go 生态中处理金额字段的事实标准组合——既保持数据库层面的强类型约束,又确保应用层全程零精度丢失。










