生产环境必须用 pgxpool.pool,因其支持连接复用、健康检查、自动重连和 context 取消;pgx.connect 和 sql.open+lib/pq 均不满足高并发与稳定性要求。

生产环境必须用 pgxpool.Pool,不是 pgx.Connect 或 sql.Open + lib/pq;连接字符串里密码含特殊字符会直接解析失败,sslmode=disable 只能用于本地开发。
为什么 pgxpool.Pool 是唯一合理选择
因为连接复用不是可选项,而是高并发下的生存线。用 pgx.Connect 每次都新建 TCP 连接,QPS 上去立刻触发 dial tcp: lookup xxx: no such host 或 too many connections;sql.Open("postgres", dsn) 虽然返回 *sql.DB,但底层若配的是 lib/pq,它已归档、不维护,且 SSL 行为和类型映射不如 pgx 稳定。
-
pgxpool.Pool内置健康检查、自动重连、连接空闲回收,pool.Ping()会真实握手并快速反馈 DNS/认证问题 - 它默认支持
context取消,事务超时、查询中断都靠它,不是靠 SQL 层的SET statement_timeout - 别被
pgx/v5/pgxpool的路径迷惑——它就是标准入口,不是“额外封装”
连接字符串写错的三个高频坑
90% 的 “连不上” 都卡在这三处,跟驱动无关。
-
host填localhost却跑在 Docker 里 → 改成容器名(如postgres)或宿主机 Docker 网桥 IP(如172.17.0.1) -
port漏写 → 即使是 5432 也建议显式写上,云服务(如 AWS RDS)常改端口,不写就连错默认库 - 密码含
@、/、:→ 必须用url.UserPassword构造,或手动url.QueryEscape,否则pgx.ParseConfig解析失败,报错像invalid URL escape
初始化后必须立刻 Ping,不能等第一次 Query
sql.Open 和 pgxpool.New 都只是初始化结构体,不建任何 TCP 连接。等到第一次 pool.Query 才暴露问题,此时错误堆栈深、定位难。
- 调
pool.Ping(context.Background()),失败就 panic 或加指数退避重试(K8s 场景下 DNS 就绪慢很常见) - 别用
db.PingContext混用——如果用了pgxpool.Pool,就只用它的Ping方法,行为更确定 - 本地开发可设
sslmode=disable,但上线必须换sslmode=require或verify-full,PostgreSQL 12+ 默认拒接非 SSL 连接
NULL 值处理不规范,Scan 直接 panic
PostgreSQL 的 NULL 映射到 Go 值类型(如 string、int)会触发 sql: Scan error on column index X: unsupported Scan, storing driver.Value type <nil> into type *string</nil>。
- 字段可能为空 → 结构体字段声明为指针:
Name *string,Scan 时传&user.Name - 或用
sql.NullString/sql.NullInt64等标准包装类型,它们自带Valid字段判断是否为 NULL - 别依赖
coalesce兜底来绕过——它解决不了类型不匹配,只是掩盖问题
最易被忽略的是:事务里混用 pool.Query 和 tx.Query。前者从池拿新连接、自动提交;后者才属于当前事务。表面跑通,实则隔离级别失效、锁范围错乱、甚至出现 current transaction is aborted。这事没法靠日志发现,得靠代码审查。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











