database/sql
database/sql
标准本身 不支持 uint64。rsc 的看法([1], [2])是:
- 有部分数据库不支持 uint64(比如 SQLite)
- database/sql 的 Value 体系中,使用一个 int64 类型来表达所有的数据库整型值;这样使得 Driver 的实现简单,只需要处理一个 int 类型(而不需要对 int8,int16 等一起处理)
- 如果 MySQL 的 driver 需要支持 uint64,它仍然可以自行支持,不需要改动 database/sql 的代码
有 proposal 期望 Go 2 的 ColumnType
中可以 加入 signedness 信息,但是被拒绝了。
MySQL Driver
go-sql-driver/mysql 在 2015 年已经 实现了对 uint64 的支持。你可以:
- 把 DB 的值 Scan 到一个 uint64 对象中
- 写 DB 时(
Exec
)使用 uint64 对象作为写入参数
GORM
GORM(v1.22.4)也实现了对 BIGINT UNSIGNED
列的(非完美)支持(当然是在 go-sql-driver/mysql 的基础上)。GORM 可以把数据保存到:
- 某个
struct
value 中:此时只要BIGINT UNSIGNED
列对应的 field 是uint64
类型,可以正常读进去 - 某个
map[string]interface{}
;如果:- 当该列是可以为 null 且值大于
int64
范围时,GORM 会报错;这个问题可以用我维护的 fork 解决 - 否则能正确地读到
uint64
值
- 当该列是可以为 null 且值大于
老版本问题
老版本(v1.21.15)GORM 的支持更差些。比如 db.ScanRows()
处理不了大于 int64 范围的整数:
converting driver.Value type []uint8 ("9223372036854775809") to a int64: value out of range
但是 db.Find()
却可以。后面作者 fix 了这个问题。