Go语言连接MySQL数据库:sqlx库实操指南
本文将详细介绍如何使用 Go 语言的 sqlx 库连接并操作 MySQL 数据库。内容包括依赖安装、连接池配置、常用查询方法(Query/Get/Select)以及事务处理,帮助开发者实现更高效的数据交互。
准备条件
第1步:安装依赖包
在使用 sqlx 之前,需要确保安装了基础的 database/sql 驱动以及 sqlx 扩展库。打开终端执行以下命令:
go get "github.com/go-sql-driver/mysql"
go get "github.com/jmoiron/sqlx"
连接数据库
第2步:初始化数据库连接
使用 sqlx.Open 建立连接。不同于原生 sql.Open,建议显式检查连接状态并通过 Ping() 验证连通性。
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB //全局对象db
func initDB() (err error) {
db, err = sql.Open("mysql","root:admin123@tcp(127.0.0.1:3306)/dududu?charset=utf8")
if err!=nil{
return err
}
err = db.Ping() //校验数据库连接
if err!=nil{
return err
}
return nil
}
func queryRowDemo() {
// 注意:实际使用中需传入指针
type User struct {
SpuID string
Title string
Price string
}
var u User
sqlStr := "select spu_id,title,price from dududu_shops where id = ?"
err:=db.QueryRow(sqlStr, 101).Scan(&u.SpuID,&u.Title,&u.Price)
if err!=nil{
fmt.Println("Error:", err)
}
fmt.Println(u)
}
func main() {
err:=initDB()
if err!=nil{
fmt.Println("Init Error:", err)
return
}
queryRowDemo()
}
第3步:优化连接池设置
生产环境中应合理配置连接池参数以避免资源耗尽或连接数不足:
SetMaxOpenConns(n int):设置最大打开的连接数。SetMaxIdleConns(n int):设置保留在连接池中的最大空闲连接数。
注:golang.org/x/net/context 相关的超时控制可能需要引入额外的包,此处仅展示基础池设置。
Db.SetMaxOpenConns(30) Db.SetMaxIdleConns(15)
建表基础
下文所有 CRUD 示例均基于以下表结构进行操作:
CREATE TABLE `userinfo` (
`uid` INT(10) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(64) DEFAULT NULL,
`password` VARCHAR(32) DEFAULT NULL,
`department` VARCHAR(64) DEFAULT NULL,
`email` varchar(64) DEFAULT NULL,
PRIMARY KEY (`uid`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8
数据处理核心概念
sqlx 在原生 database/sql 基础上提供了更便捷的数据转换方式。主要包含以下几类 Handle Types 和 Cursor:
- Handle Types:
sqlx.DB:表示数据库连接。sqlx.Tx:表示事务。sqlx.Stmt:预编译语句。sqlx.NamedStmt:支持命名参数的预编译语句。
- Cursor Types:
sqlx.Rows:用于遍历多行结果。sqlx.Row:用于获取单行结果。
- 新增功能:提供了
Get(dest interface{}, ...)和Select(dest interface{}, ...),可直接将查询结果映射到结构体切片或单个结构体中。
Exec 使用:增删改操作
第4步:执行插入、更新和删除
Exec 方法适用于不返回行的 SQL 操作(如 INSERT, UPDATE, DELETE)。注意 MySQL 占位符为 ?,不同数据库可能不同(如 Oracle 使用 :name)。
package main
import (
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
"fmt"
)
var Db *sqlx.DB
func init() {
var db *sqlx.DB
var err error
db, err = sqlx.Open("mysql", "stu:1234qwer@tcp(10.0.0.241:3307)/test?charset=utf8")
if err != nil {
fmt.Println("open mysql failed,", err)
return
}
Db = db
}
func main() {
// 插入
result, err := Db.Exec("INSERT INTO userinfo (username, password, department,email) VALUES (?, ?, ?,?)",
"wd","123","it","wd@163.com")
if err != nil{
fmt.Println("insert failed,error: ", err)
return
}
id,_ := result.LastInsertId()
fmt.Println("insert id is :",id)
// 更新
_, err1 := Db.Exec("update userinfo set username = ? where uid = ?","jack",1)
if err1 != nil{
fmt.Println("update failed error:",err1)
} else {
fmt.Println("update success!")
}
// 删除
_, err2 := Db.Exec("delete from userinfo where uid = ? ", 1)
if err2 != nil{
fmt.Println("delete error:",err2)
}else{
fmt.Println("delete success")
}
}
预声明语句(Prepared Statements)
预编译语句可以提升重复执行的效率,并防止 SQL 注入。
原生 Prepare 用法:
stmt, err := db.Prepare(`SELECT * FROM place WHERE telcode=?`) row = stmt.QueryRow(65)
sqlx 扩展了 Preparex,可直接关联结构体:
stmt, err := db.Preparex(`SELECT * FROM place WHERE telcode=?`) var p Place err = stmt.Get(&p, 852)
Query 系列:读取数据
第5步:传统扫描 Row Scan
Query 返回 *sql.Rows 对象,需手动迭代并使用 Scan 赋值给变量。务必在循环结束后检查错误,并确保 rows.Close() 被调用以释放连接。
rows, err := Db.Query("SELECT username,password,email FROM userinfo")
if err != nil{
fmt.Println("query failed,", err)
return
}
defer rows.Close()
for rows.Next() {
var username,password,email string
err = rows.Scan(&username, &password, &email)
if err != nil { panic(err) }
println(username,password,email)
}
第6步:使用 StructScan 简化读取
Queryx 配合 StructScan 可将一行数据直接转换为结构体字段,前提是结构体标签需指定列名(如 `db:"username"`)。
type stu struct {
Username string `db:"username"`
Password string `db:"password"`
Department string `db:"department"`
Email string `db:"email"`
}
rows, err := Db.Queryx("SELECT username,password,email FROM userinfo")
for rows.Next() {
var s stu
err = rows.StructScan(&s)
fmt.Println(s.Username)
}
第7步:获取单行 Get/QueryRow
QueryRow 返回 *sql.Row,如果查询结果为空会返回 sql.ErrNoRows。
var s stu
// QueryRowx 可直接绑定到结构体
err1 := Db.QueryRowx("SELECT username,password,email FROM userinfo where uid = ?",2).StructScan(&s)
if err1 != nil{
fmt.Println("Error :",err1)
}else {
fmt.Printf("Result:%v\n",s)
}
第8步:批量查询 Select
Get 用于单次结果映射,Select 用于多条记录映射到切片,这是最常用的两种模式。
var stus []stu
// 获取所有记录
err := Db.Select(&stus,"SELECT username,password,email FROM userinfo")
if err != nil{
fmt.Println("Select error",err)
}
fmt.Printf("All users: %v\n",stus)
var s stu
// 获取单条记录
err1 := Db.Get(&s,"SELECT username,password,email FROM userinfo where uid = ?",2)
if err1 != nil{
fmt.Println("GET error :",err1)
}else {
fmt.Printf("Single user: %v\n",s)
}
事务(Transactions)
事务操作保证了一组操作的原子性,要么全部成功,要么全部回滚。关键步骤包括 Begin、Exec、Commit 和 Rollback。
tx, err := Db.Beginx()
// 第一笔操作
_, err = tx.Exec("insert into userinfo(username,password) values(?,?)", "Rose","2223")
if err != nil {
tx.Rollback() // 出错立即回滚
fmt.Println("exec sql error:", err)
return
}
// 第二笔操作
_, err = tx.Exec("insert into userinfo(username,password) values(?,?)", "Mick",222)
if err != nil {
tx.Rollback()
fmt.Println("exec sql error:", err)
return
}
// 提交事务
err = tx.Commit()
if err != nil {
fmt.Println("commit error")
}
注意:Tx 对象持有单一连接,因此必须尽快 Commit 或 Rollback 以释放资源,避免连接池泄漏。
完整案例演示
以下是一个结合初始化与基本查询的整合示例:
var Db *sqlx.DB
db, err := sqlx.Open("mysql","root:admin123@tcp(127.0.0.1:3306)/dududu?charset=utf8")
Db = db
rows, err := Db.Query("SELECT spu_id,title,price FROM dududu_shops")
if err != nil{
fmt.Println("query failed,", err)
return
}
defer rows.Close()
for rows.Next() {
var spu_id,title,price string
err = rows.Scan(&spu_id, &title, &price)
if err != nil { panic(err) }
println(spu_id,title,price)
}以上就是 Go 语言利用 sqlx 库连接并操作 MySQL 数据库的详细内容,更多关于 Golang 操作数据库的实践技巧请持续关注本站后续文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









