如何在Golang中使用MySQL数据库_Golang与MySQL数据库连接与操作

1次阅读

go连接mysql最稳妥方式是database/sql加go-sql-driver/mysql驱动;需显式导入驱动,正确配置连接字符串,区分Query/QueryRow/Exec用途,仅用?占位防注入,手动管理事务,并显式设置连接池参数。

如何在Golang中使用MySQL数据库_Golang与MySQL数据库连接与操作

Go 语言连接 MySQL 最稳妥的方式是用 database/sql + github.com/go-sql-driver/mysql,不是 ORM,也不是封装层,而是标准接口+专用驱动的组合——它不隐藏细节,出错时你能直接看到 SQL 执行链路上哪一环断了。

安装驱动并建立基础连接

Go 没有内置 MySQL 驱动,必须显式引入第三方驱动。仅导入 database/sql 是不够的,会 panic:”sql: unknown driver ‘mysql‘”。

  • 运行 go get -u github.com/go-sql-driver/mysql
  • 在代码中同时导入:"database/sql""github.com/go-sql-driver/mysql"(后者仅需导入,无需赋值或调用)
  • 连接字符串格式为:"user:password@tcp(127.0.0.1:3306)/dbname?parseTime=true&loc=Local";注意 & 是 URL 中的 & 字符,不能写成 &
  • parseTime=true 让驱动把 DATETIME / timestamp 自动转成 time.Timeloc=Local 避免时区错乱(否则可能默认 UTC)

Query、QueryRow 与 Exec 的分工

这三个方法不 interchangeable:选错会导致死锁、漏扫描、或误吞错误。

  • db.Query() 用于 select 多行,返回 *sql.Rows,**必须调用 rows.Close()**(哪怕只读一行),否则连接不会释放
  • db.QueryRow() 用于确定只返回一行的 SELECT(如带 LIMIT 1 或主键查询),它内部自动 Close,但你要用 .Scan() 拿数据,否则 Scan 错误会被静默丢弃
  • db.Exec() 用于 INSERT/UPDATE/delete,返回 sql.Result,可调 .LastInsertId().RowsAffected();**不能用它执行 SELECT**,否则返回空结果且无报错

防止 SQL 注入:只用问号占位符,不用字符串拼接

MySQL 驱动不支持命名参数(如 :name@id),只认 ?,且参数必须是切片或单独值,不能是 map结构体

立即学习go语言免费学习笔记(深入)”;

  • 正确:db.Query("SELECT name FROM users WHERE id > ?", minID)db.Query("SELECT * FROM logs WHERE level IN (?, ?)", "warn", "Error")
  • 错误:"SELECT * FROM users WHERE name = '" + name + "'" —— 直接给注入留门
  • 错误:db.Query("SELECT * FROM users WHERE id IN (?)", []int{1,2,3}) —— ? 只展开为单个值,不会变成 IN (1,2,3);需动态拼 ?, ?, ? 再传参

事务控制:Begin → Exec/Query → Commit/Rollback

事务不是自动开启的,每次 db.Querydb.Exec 都是独立语句。要跨多步原子操作,必须显式管理事务对象

  • tx, err := db.Begin() 获取事务,后续所有操作都调 tx.Query / tx.Exec
  • 成功后调 tx.Commit();失败必须调 tx.Rollback(),否则连接会卡在“事务中”状态,最终被连接池回收时触发 warning
  • 注意:事务内不能混用 db.*tx.*,否则语句脱离事务上下文
  • 如果中间某步出错忘了 Rollback,又没 defer,这个事务连接大概率会在下次复用时因状态异常被丢弃

最常被忽略的是连接池行为:默认最大打开连接数是 0(无限制),但在高并发下容易耗尽 MySQL 的 max_connections;建议显式调 db.SetMaxOpenConns(n)db.SetMaxIdleConns(n),否则线上跑几天后可能突然大量超时,而错误日志里只显示 “i/o timeout”,实际是连接等不到空闲槽位。

text=ZqhQzanResources