database/sql连接池必须全局复用,不可在handler中反复open/close;应启动时initdb初始化*sql.db并调用ping验证,通过setmaxopenconns和setmaxidleconns合理限制连接数以防打爆数据库。

database/sql 连接池必须全局复用,别在 handler 里反复 Open/Close
很多人一写 HTTP handler 就习惯 sql.Open → 操作 → db.Close(),这是典型反模式。连接池不是“连接”,而是管理一堆连接的结构体;sql.Open 不建连,只初始化池;db.Close() 会把整个池关掉,后续所有查询直接 panic。
- 启动时调用一次
initDB()初始化*sql.DB,赋值给包级变量或注入到 service 层 - 务必调用
db.Ping()验证配置是否生效,否则错误会延迟到第一次查询才暴露 - 设置连接池参数:用
db.SetMaxOpenConns(20)和db.SetMaxIdleConns(10)控制并发上限,避免打爆 PostgreSQL 的max_connections - PostgreSQL 默认
max_connections=100,若服务实例多、又没调小池大小,很容易触发too many clients already
用 pgx 而不是 pq?看场景,别盲目追新
github.com/jackc/pgx/v5 在批量插入、JSONB 直接扫描、类型映射精度上确实比 github.com/lib/pq 强,但它不兼容 database/sql 接口(v5 之后需显式使用 pgxpool.Pool),意味着你得重写所有 QueryRow/Exec 调用。
- 新项目且需要 PostgreSQL 特性(如数组、range、自定义类型)→ 直接上
pgxpool - 已有项目用
pq稳定运行,无性能瓶颈 → 别动,迁移成本远高于收益 - 注意
pgx的Conn不是线程安全的,必须从pgxpool.Pool获取并及时conn.Close(),否则连接泄漏 -
pq对time.Time默认按 UTC 解析,pgx默认按本地时区,跨服务时间字段容易错位,务必统一配置timezone=utc在连接字符串里
GORM 在微服务里不是银弹,慎用 AutoMigrate
微服务强调数据库私有性,每个服务应只读写自己的库表。GORM 的 AutoMigrate 会尝试 ALTER 表结构,一旦多个服务指向同一数据库(哪怕只是测试环境),极易引发竞态 DDL 冲突,比如两个服务同时加同一个字段,一个成功一个失败。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 生产环境禁用
AutoMigrate,改用golang-migrate做版本化 SQL 迁移 - 如果坚持用 GORM,至少关闭自动迁移:
gorm.Config{DisableAutomaticPing: true, AutoMigrate: false} - GORM 的
Preload在 N+1 场景下很危险——它生成多条 SELECT,而微服务间网络延迟高,不如手写 JOIN 或分两步查 - 事务控制必须显式传入
*gorm.DB实例,不能依赖全局db变量,否则跨 goroutine 会污染事务上下文
别让 SQL 注入和 panic 毁掉你的服务稳定性
Go 的 database/sql 错误不 panic,但开发者常犯两类致命错误:拼接 SQL 字符串、忽略 rows.Err()、对 Scan 失败不检查。
- 永远用
db.Query("SELECT * FROM users WHERE id = $1", userID),别写"WHERE id = " + strconv.Itoa(id) -
rows, err := db.Query(...)后,必须defer rows.Close(),且循环结束后检查rows.Err()—— 它可能包含查询中途的网络中断 -
err := rows.Scan(&u.Name, &u.Email)失败时,err可能是sql.ErrNoRows(正常),也可能是类型不匹配(bug),别直接if err != nil { panic(err) } - PostgreSQL 错误码比 MySQL 丰富,遇到
pq.Error.Code == "23505"(唯一约束冲突)应转成业务错误返回,而不是吐给前端 500
实际跑通一条查询链路,关键不是“怎么写”,而是“谁负责清理、谁承担超时、谁解析错误”。微服务里数据库操作的脆弱点,往往藏在连接复用边界、驱动行为差异、ORM 隐式假设这些地方,而不是语法本身。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










