跳转到主内容
极星编程网:以代码为星,赴技术山海!

Go语言Gin怎么连接MySQL_Go语言Gin操作MySQL教程【简明】

Gin 不处理数据库连接,需用 database/sql 配 MySQL 驱动;sql.Open 仅校验 DSN,须 db.Ping() 测试连通;*sql.DB 应挂载到 Gin 上供 handler 使用;Query 返回的 rows 必须显式 Close() 防泄漏;QueryRow 自动关闭;Scan 须严格匹配字段顺序、类型及 NULL 处理;事务中必须统一使用 tx 对象,避免混用 db 和 tx。 Go Gin 里用
database/sql
连 MySQL,不是用 Gin 自己连 Gin 本身不处理数据库连接,它只管 HTTP 路由和响应。真正连 MySQL 的是 Go 标准库
database/sql
,配合 MySQL 驱动(比如
github.com/go-sql-driver/mysql
)。很多人卡在第一步:以为 Gin 提供了
gin.DB()
这种方法,其实没有。 实操建议: 先
go get github.com/go-sql-driver/mysql
安装驱动 用
sql.Open("mysql", "user:pass@tcp(127.0.0.1:3306)/dbname?parseTime=true&loc=Local")
初始化连接池,注意参数里
parseTime=true
和
loc=Local
要加,否则
time.Time
字段可能解析失败或时区错乱 别忘了调
db.Ping()
检查连通性,
sql.Open
只校验 DSN 格式,不真正建连 把
*sql.DB
实例挂到 Gin 的
gin.Engine
上,常用方式是
engine.Use(func(c *gin.Context) { c.Set("db", db) })
,后续 handler 里用
c.MustGet("db").(*sql.DB)
取 Query 和 QueryRow 返回的
sql.Rows
必须显式
Close()
这是最常被忽略的资源泄漏点。Gin handler 里写
rows, err := db.Query("SELECT ...")
后,如果没调
rows.Close()
,连接会一直占着,很快耗尽连接池(尤其高并发时)。 常见错误现象: 立即学习 “ go语言免费学习笔记(深入) ”; 请求变慢、超时,日志里出现
dial tcp 127.0.0.1:3306: connect: cannot assign requested address
MySQL 侧看到大量
Sleep
状态连接 正确做法: 用
defer rows.Close()
—— 但注意:必须在
for rows.Next()
循环结束后再 defer,否则循环中途就关了 更稳妥的是把
rows.Close()
放在 for 循环之后、函数 return 前,或者用
if rows != nil { defer rows.Close() }
包一层
QueryRow
不需要手动 Close,它内部自动处理 用
Scan
读数据时,变量顺序、类型、数量必须和 SELECT 字段严格一致 MySQL 查询字段顺序变了、加了新字段、用了别名但没对应上变量,
Scan()
就会直接 panic 或静默失败(比如把 int 扫成 string),而且错误信息往往不明确。 go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载 使用场景举例:你写
SELECT id, name, created_at FROM users
,那
Scan(&id, &name, &createdAt)
三个变量顺序不能错,且
createdAt
类型得是
time.Time
(前提是 DSN 里开了
parseTime=true
)。 容易踩的坑: SELECT 里用了函数或表达式(如
UNIX_TIMESTAMP(created_at)
),结果类型是
int64
,但你还用
time.Time
变量去 Scan → panic 字段有 NULL,但用非指针类型接收(如
string
而非
*string
)→
sql: Scan error on column index 1
用
SELECT *
,表结构一变,代码立刻崩,别这么干 事务里别混用
db.Query
和
tx.Query
一旦开始事务(
tx, _ := db.Begin()
),所有操作必须走
tx
对象,比如
tx.Query
、
tx.Exec
。如果在事务中误用了
db.Query
,那这条语句根本不在事务里,也不会受
tx.Commit()
或
tx.Rollback()
控制。 性能与一致性影响: 看似成功提交,其实部分数据已落库(
db.Query
那条),事务原子性彻底失效 调试时很难发现,因为没报错,只是逻辑错乱 实操建议: 事务内统一用
tx
;handler 函数开头就判断是否在事务上下文里(比如通过
c.Get("tx")
),避免混用 事务结束前,记得
tx.Commit()
或
tx.Rollback()
,后者尤其重要——panic 或 error 时没 rollback,连接就卡死在事务中 别依赖 defer 做 rollback:
defer tx.Rollback()
在 Commit 成功后也会执行,导致二次 rollback 报错 真正的难点不在语法,而在连接生命周期管理、资源释放时机、事务边界控制这些“看不见”的地方。写完一行
db.Query
,得立刻想清楚:它什么时候关?在哪关?会不会和其他操作串了?

相关文章