Go 的 database/sql 是抽象接口层,需显式导入驱动;sql.Open 不建连,须调用 db.Ping() 验证;密码含特殊字符需 url.QueryEscape;QueryRow 延迟报 sql.ErrNoRows,Query 需手动检查 rows.Err() 并调用 rows.Close();字段名须与列名完全一致且区分大小写;预处理语句需按场景使用;连接池参数 SetMaxOpenConns 等必须合理配置。

Go 的 database/sql 不是数据库驱动,而是抽象接口层 —— 你必须显式导入并注册驱动(如 github.com/lib/pq 或 github.com/go-sql-driver/mysql),否则 sql.Open 会返回 "sql: unknown driver" 错误。
初始化连接时必须调用 db.Ping() 验证连通性
sql.Open 只校验参数、不建立真实连接;真正报错常发生在首次查询时。生产环境务必在初始化后立即执行 db.Ping(),避免服务启动后首请求失败。
- 使用
context.WithTimeout控制探测时间,防止卡死:ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() if err := db.PingContext(ctx); err != nil { log.Fatal("DB ping failed:", err) } - 连接字符串中的密码若含特殊字符(如
@、/),需用url.QueryEscape编码,否则解析失败 - MySQL 驱动默认不启用自动重连,连接中断后需自行处理重试逻辑或使用连接池配置
QueryRow 和 Query 的行为差异直接影响错误处理方式
QueryRow 适用于单行结果(如 SELECT ... LIMIT 1),它把 NoRows 错误延迟到 Scan 阶段才暴露;而 Query 返回 *Rows,需手动检查 rows.Err() 并调用 rows.Close()。
-
QueryRow(...).Scan(&v)失败时,err可能是sql.ErrNoRows,也可能是类型不匹配或网络错误 —— 别直接忽略sql.ErrNoRows - 用
Query循环读取时,必须在for rows.Next()后调用rows.Close(),否则连接不会归还给池,最终耗尽连接数 - 扫描结构体字段时,字段名必须与 SQL 列名(或别名)**完全一致且区分大小写**,否则值为零值且无提示
预处理语句(Prepare)不是性能银弹,要分场景使用
对于高频执行的相同 SQL(尤其带参数的 DML),Stmt 能复用执行计划、减少 SQL 解析开销;但对一次性查询或低频操作,直接用 Exec/Query 更轻量,且避免 Stmt 泄漏风险。
动态WEB网站中的PHP和MySQL详细反映实际程序的需求,仔细地探讨外部数据的验证(例如信用卡卡号的格式)、用户登录以及如何使用模板建立网页的标准外观。动态WEB网站中的PHP和MySQL的内容不仅仅是这些。书中还提到如何串联JavaScript与PHP让用户操作时更快、更方便。还有正确处理用户输入错误的方法,让网站看起来更专业。另外还引入大量来自PEAR外挂函数库的强大功能,对常用的、强大的包
立即学习“go语言免费学习笔记(深入)”;
- 不要在循环内反复
db.Prepare—— 每次都新建 Stmt,容易触发"too many connections" - Stmt 本身不是线程安全的,但
*sql.DB是;推荐复用db.Exec等方法,让连接池内部管理预处理 - PostgreSQL 驱动对未命名的
PREPARE有隐式缓存,但 MySQL 驱动(go-sql-driver/mysql)默认关闭 server-side prepare,需显式加parseTime=true&loc=Local参数并确认版本支持
最易被忽略的是连接池配置:SetMaxOpenConns、SetMaxIdleConns、SetConnMaxLifetime 这三个参数不设默认值或设得不合理,会导致连接堆积、DNS 失效未清理、或长连接僵死。特别是云数据库(如 AWS RDS、阿里云 PolarDB)常配置了连接空闲超时,必须让 ConnMaxLifetime 小于该值,否则连接池会持续复用已断开的连接。









