在 Golang 中使用 sqlx 对 MySQL 的查询时, 如果数据库中某个字段的值是 NULL, 对应的结构体里面的字段类型是 int64, 就会报以下错误:
converting null to int64 is unsupported
database/sql
包里面有一个 NullInt64
类型:
// NullInt64 represents an int64 that may be null.
// NullInt64 implements the Scanner interface so
// it can be used as a scan destination, similar to NullString.
type NullInt64 struct {
Int64 int64
Valid bool // Valid is true if Int64 is not NULL
}
会把值存在 Int64, 如果是Null 则 Valid=false
, 否则 Valid=true
, 但是这是一个结构体, 在使用的时候比较麻烦, 当转 JSON 的时候也多了一个嵌套, 例如(cid 类型是 sql.NullInt64):
{
"name": "xx",
"cid": {
"Int64": 2,
"Valid": true
}
}
本来一个数值类型的, 现在变成了一个嵌套的值.
其实可以自己实现一个 NullInt64, 不使用结构体, 实际使用中和 int64 基本没有太大区别.
type NullInt64 int64
func (ni *NullInt64) Scan(value interface{}) error {
if value == nil {
*ni = 0
return nil
}
var val string
switch v := value.(type) {
case string:
val = v
case []byte:
val = string(v)
}
i64, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return err
}
*ni = NullInt64(i64)
return nil
}
func (ni NullInt64) Value() (driver.Value, error) {
if ni == 0 { // if nil or empty string
return nil, nil
}
return int64(ni), nil
}
在查询数据库的时候, NullInt64
会调用 Scan
方法. 其他的类型遇到类似的问题, 可以参考此解决方案.