必须用sql.NullString当数据库字段允许NULL且用string接收时,否则Scan报错;字段定义NOT NULL或业务确保非NULL时可用原生string。
sql.NullString 什么时候必须用,什么时候可以不用
Go 的
包不会自动把数据库里的
映射成 Go 的零值(比如空字符串),而是直接报错:
。所以只要字段在数据库里允许为
,且你用的是普通
类型接收,就一定会崩——这时候
不是“可选优化”,是刚需。
反过来说:如果字段定义了
,或者你确定永远不会有
(比如刚插入的记录、有严格业务校验),那用原生
更干净,没必要套一层
。
常见错误现象:用
接收可能为
的列,查询时 panic 或静默失败
性能影响极小,只是多一个
字段,无额外内存分配或 GC 压力
注意:它不是泛型,
、
等需按类型分别选用
Scan 到 struct 时怎么正确绑定 sql.NullString
不能直接在 struct 字段上写
,得显式声明为
,然后靠
自动识别其
方法。否则会因类型不匹配跳过赋值,字段保持零值但
仍为
,容易误判。
示例:
立即学习
“
go语言免费学习笔记(深入)
”;
go语言参考手册 中文CHM版
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译
下载
必须取地址传给
(
),否则不会修改原字段
是值,不是方法;它只是个普通字段,和
并列
别在 struct tag 里加
这类——标准库不认,纯属干扰
从 NullString 安全转回 string 的三种写法及区别
没有“默认 fallback”的魔法函数,你要自己决定
时返回什么。最常见的是空字符串、占位符或 panic,但每种都有隐含逻辑风险。
:不管
直接取值——
时返回空字符串,但你无法区分“真是空”还是“数据库 NULL”
:推荐。明确分离两种语义,避免数据污染
类拼接:危险!
时
是空串,结果变成
,业务逻辑可能出错
特别注意:
的零值是
,所以新声明的变量默认就是 “NULL 状态”,别依赖初始化值做判断。
ORM(如 GORM)里要不要还手动用 sql.NullString
GORM v2 默认会自动处理
:字段声明为
就能接
,
反而会被当成普通 struct 处理,导致扫描失败或字段被忽略。
GORM 推荐写法:
(指针),
→
,非空 → 指向字符串
如果你混用
原生查询和 GORM,保持类型统一反而更麻烦,建议全切到一种风格
第三方驱动(如 pgx)可能提供更高级的
类型,但跨库迁移成本高,除非真有性能瓶颈,否则 sticking with
更稳
最易被忽略的一点:JSON 序列化时,
默认输出为
,不是字符串。要兼容 API 返回,得自己实现
,或者中间转成
再序列化。
database/sqlNULLsql: Scan error on column index 0: unsupported Scan, storing driver.Value type into type *string NULLstringsql.NullStringNOT NULLNULLstringsql.NullStringstringNULLValid boolsql.NullInt64sql.NullBoolstringsql.NullStringScanScanValidfalsetype User struct {
ID int
Name sql.NullString
Email sql.NullString
}
var u User
err := db.QueryRow("SELECT id, name, email FROM users WHERE id = ?", 1).Scan(&u.ID, &u.Name, &u.Email)
if err != nil {
// 处理 err
}
// 使用前必须检查 Valid
if u.Name.Valid {
fmt.Println("Name:", u.Name.String)
} else {
fmt.Println("Name is NULL")
}Scan&u.Namesql.NullString.StringValidsql:"name"NULLu.Name.StringValidNULLif u.Name.Valid { ... } else { ... }u.Name.String + " (nullable)"NULLString" (nullable)"sql.NullString{String: "", Valid: false}NULL*stringNULLsql.NullStringName *stringNULLnildatabase/sqlNullXXXsql.Null*sql.NullString{"String":"xxx","Valid":true}MarshalJSON*string