postgresql在go中需显式引入驱动,推荐新项目使用pgx/v5;连接字符串须含sslmode=disable等参数;用pgxpool管理连接池;null值处理应使用pgtype类型。

PostgreSQL 在 Go 中不是开箱即用的,必须显式引入驱动并手动管理连接——database/sql 本身不包含任何数据库实现,它只提供抽象接口。
安装 pgx 或 pq 驱动?选哪个更稳妥
Go 生态主流 PostgreSQL 驱动有两个:pgx(Jackc 开发)和 pq(已归档,仅维护 bug)。pq 虽仍可用,但不再新增特性;pgx 性能更好、支持原生类型(如 jsonb 直接映射为 map[string]interface{})、提供连接池和高级查询构造能力。
- 新项目直接用
github.com/jackc/pgx/v5,v5 是当前稳定版,注意导入路径含/v5 - 若需兼容
database/sql接口(比如用sqlx),用pgx/v5/pgxpool或pgx/v5/pgconn+pgx/v5/pgxpool的StatDB()方法桥接 - 避免混用
pq和pgx:它们注册的驱动名不同(pq是postgres,pgx默认也是postgres,但行为不兼容)
连接字符串写法与常见错误
PostgreSQL 连接字符串格式灵活,但参数名和值必须严格匹配。最简可用形式是 URL 格式:postgres://user:password@localhost:5432/dbname?sslmode=disable。漏掉 sslmode=disable 在本地开发时大概率报错:SSL is not enabled on the server。
-
sslmode必须显式指定:本地开发用disable,测试/生产环境优先用require或verify-full - 密码含特殊字符(如
@、/)必须 URL 编码,否则解析失败;建议用url.UserPassword构造用户信息 - 端口不能省略:即使默认 5432,也建议显写,避免某些配置下解析歧义
- 数据库名不能为空,否则连上的是默认库(通常是
postgres),容易误操作
用 pgxpool 建立安全连接池
pgxpool.Pool 是线程安全、带健康检查和自动重连的首选方式,不要手写 sql.Open + SetMaxOpenConns 等组合。
立即学习“go语言免费学习笔记(深入)”;
pool, err := pgxpool.New(context.Background(), "postgres://user:pass@localhost:5432/mydb?sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer pool.Close()
// 使用前 ping 检查连通性
if err := pool.Ping(context.Background()); err != nil {
log.Fatal("failed to ping db:", err)
}
- 不要在每次查询前调用
pool.Acquire后又立刻Release:这会抵消连接复用优势;应把业务逻辑包在pool.Query或pool.QueryRow内部 - 设置
max_conns参数要结合实际负载:默认是 4,高并发服务通常设为 20–50;过大会压垮 PostgreSQL(每个连接约占用几 MB 内存) - 环境变量传连接串更安全:
os.Getenv("DATABASE_URL"),避免硬编码密码
查询结果扫描时最容易忽略的空值处理
PostgreSQL 的 NULL 和 Go 的零值不是一回事。用 Scan 或 Row.Scan 时,如果字段可能为 NULL,必须用指针或 sql.NullXXX 类型接收,否则会 panic 或静默丢数据。
- 推荐用
pgx自带的pgtype类型(如pgtype.Text、pgtype.Int4),它们自带Valid字段,比sql.NullString更贴合 PostgreSQL 类型系统 - 结构体扫描时,字段类型必须和数据库列类型对齐:例如
uuid列对应pgtype.UUID,不是string - 批量查询用
pgx.Rows时,记得在循环结束后调用rows.Close(),否则连接不会归还池中
真正麻烦的从来不是连上数据库,而是连接生命周期管理、NULL 处理、事务边界控制和连接泄漏排查——这些细节在日志里往往只体现为“context deadline exceeded”或“too many clients”,但根源常在初始化或扫描环节。










