
本文介绍使用 lib/pq 驱动时,如何正确扫描并解码 PostgreSQL 的 ARRAY 类型(如 ARRAY_AGG 结果)为 Go 原生切片,避免因类型不匹配导致的程序挂起问题。
本文介绍使用 lib/pq 驱动时,如何正确扫描并解码 postgresql 的 array 类型(如 `array_agg` 结果)为 go 原生切片,避免因类型不匹配导致的程序挂起问题。
在 Go 中操作 PostgreSQL 时,若 SQL 查询返回了数组类型(例如通过 ARRAY_AGG(code) 聚合生成的 {H01,H02}),直接使用 row.Scan(&id, &codes) 会导致程序静默阻塞——既无 panic,也无错误日志。这是因为 lib/pq 默认将 PostgreSQL 数组反序列化为 []byte 或 string,而 Go 的 sql.Scanner 无法自动将其转换为 []string 等目标类型,从而引发底层读取卡死。
解决方法是显式使用 pq.Array 包装目标切片指针,告知驱动按 PostgreSQL 数组协议进行解析:
import (
"database/sql"
"log"
"github.com/lib/pq"
)
var id string
var codes []string // 注意:必须是切片类型(如 []string, []int64),而非 string
err := row.Scan(&id, pq.Array(&codes))
if err != nil {
log.Fatal("scan failed:", err)
}
// 成功后 codes == []string{"H01", "H02"}
✅ 关键要点:
-
pq.Array(&slice)必须传入切片变量的地址(&codes),而非切片本身; - 切片元素类型需与数据库中数组元素类型一致(如
text→[]string,integer→[]int); - 若数组可能为
NULL,建议使用sql.NullString包装或先检查row.Err(),或使用pq.NullArray(需自行实现或升级至兼容版本); - 不推荐手动
strings.Trim/strings.Split原始字符串(如"{"H01","H02"}"),因其格式依赖 PostgreSQL 的array_to_string行为,且易受转义、空格、NULL 元素影响,极不可靠。
⚠️ 注意:pq.Array 仅适用于 lib/pq 驱动;若使用 pgx,应改用 pgx/pgtype.Array 或 Scan() 方法配合 *[]string 类型。确保导入 github.com/lib/pq 并在连接字符串中指定 postgres 驱动名。
正确使用 pq.Array 后,即可稳定、高效地将 PostgreSQL 数组映射为 Go 切片,彻底规避扫描挂起问题。










