postgresql jsonb字段在go中必须用json.rawmessage或自定义struct接收,不可直接scan到string或sql.nullstring;写入null须用*json.rawmessage nil指针,查询时避免select配[]interface{}导致panic。

PostgreSQL JSONB字段在Go里怎么读出来不报错
直接用 sql.Scan 读 JSONB 字段到 string 或 []byte 是安全的,但读到 map[string]interface{} 或结构体时会 panic —— 因为 database/sql 默认不支持 JSONB 的自动反序列化。
常见错误现象:sql: Scan error on column index 0, name "data": unsupported Scan, storing driver.Value into type *map[string]interface{}
- 必须用
json.RawMessage接收原始字节,再手动json.Unmarshal - 或者用
pgx驱动(推荐),它原生支持JSONB→map[string]interface{}、struct、json.RawMessage三者直转 -
database/sql+lib/pq已废弃,不建议新项目使用;若必须用,只能走json.RawMessage中转
用 pgx 把 Go 结构体写入 JSONB 字段要填哪些坑
pgx 能直接把 struct 写进 JSONB 字段,但字段标签和类型稍有不匹配就会静默失败或存空值。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 结构体字段必须是导出的(首字母大写),否则
pgx序列化时忽略 - 推荐显式加
json标签,比如Name string `json:"name"`,避免字段名大小写错位 - 零值字段(空字符串、0、nil slice)默认也会被序列化进去;如需省略,加
omitempty:`json:"name,omitempty"` - 如果结构体含
time.Time,确保已注册pgtype.Timestamptz或用字符串字段中转,否则可能转成空对象{}
在 WHERE 条件里查 JSONB 字段的 key 和 value 怎么写才快
直接用 -> 或 ->> 操作符可以查,但没索引的话,哪怕表只有几万行,查询也会变慢。
- 查是否存在某个 key:用
data ? 'status',配合GIN索引(ON table USING GIN (data)) - 查具体 value:用
(data ->> 'status') = 'active',这时需要表达式索引:ON table USING GIN ((data ->> 'status')) - 避免写
data::text LIKE '%active%'—— 强制转字符串 + 全表扫描,数据一过万就卡 - 复合条件慎用
AND连多个->>,GIN 索引对多路径查询效率有限,必要时拆成子查询或冗余字段
更新 JSONB 字段局部内容时,为什么原字段丢了其他 key
用 json_set 或 || 拼接时漏了保留原有结构,是高频翻车点。
- 错误写法:
UPDATE t SET data = '{"status":"done"}'::jsonb→ 整个字段被覆盖 - 正确做法:
UPDATE t SET data = data || '{"status":"done"}'::jsonb(合并)或jsonb_set(data, '{status}', '"done"')(精准路径更新) - 如果用 Go 拼 SQL,注意
json.Marshal输出的双引号需被 PostgreSQL 正确识别,建议用pgx.NamedArgs绑定json.RawMessage参数,避免引号逃逸问题 - 嵌套路径更新(如
config.timeout)必须用jsonb_set,||只能顶层合并
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










