GO的sqlx包使用 | 青训营笔记

117 阅读3分钟
# 使用 Golang 操作 MySQL 数据库及第三方库 SQLx

在 Golang 中操作 MySQL 数据库是开发过程中的一个常见任务。为了简化数据库操作并提供更好的开发体验,开发者通常会使用第三方库。sqlx是一个受欢迎的 Golang 第三方库,它建立在标准库的 database/sql 包之上,提供了更强大和方便的数据库操作功能。

以下是一个使用 Golang 和 sqlx 库来连接、查询和插入数据到 MySQL 数据库的示例。

安装 SQLx

首先,你需要使用以下命令安装 xqlx 库:

 go get github.com/jmoiron/sqlx

连接到 MySQL 数据库

在使用 SQLx 进行数据库操作之前,首先需要建立连接。下面是一个连接到 MySQL 数据库的示例代码:

 import (
     "fmt"
     "log"
 ​
     "github.com/jmoiron/sqlx"
     _ "github.com/go-sql-driver/mysql" //init()
 )
 ​
 func main() {
     // 连接数据库
     dsn := "user:password@tcp(127.0.0.1:3306)/dbname"
     db, err := sqlx.Connect("mysql", dsn)
     if err != nil {
         log.Fatal(err)
     }
     defer db.Close()
 ​
     fmt.Println("成功连接到数据库")
 }

确保将 userpassworddbname 替换为你自己的 MySQL 数据库凭据和数据库名称。

查询数据

以下是使用 SQLx 进行查询的示例代码:

 func queryData(db *sqlx.DB) {
     type User struct {
         ID       int    `db:"id"`
         Username string `db:"username"`
         Email    string `db:"email"`
     }
 ​
     users := []User{}
     err := db.Select(&users, "SELECT id, username, email FROM users")
     if err != nil {
         log.Fatal(err)
     }
 ​
     fmt.Println("查询结果:")
     for _, user := range users {
         fmt.Printf("ID: %d, Username: %s, Email: %s\n", user.ID, user.Username, user.Email)
     }
 }

在这个示例中,我们定义了一个 User 结构体来映射数据库中的数据。使用 db.Select() 函数从数据库中检索数据,并将结果映射到切片中的结构体。

插入数据

以下是使用 SQLx 插入数据的示例代码:

 func insertData(db *sqlx.DB) {
     newUser := User{
         Username: "newuser",
         Email:    "newuser@example.com",
     }
 ​
     result, err := db.NamedExec("INSERT INTO users (username, email) VALUES (:username, :email)", newUser)
     if err != nil {
         log.Fatal(err)
     }
 ​
     insertID, _ := result.LastInsertId()
     fmt.Printf("插入成功,新用户的 ID 是 %d\n", insertID)
 }

在这个示例中,我们使用 NamedExec() 函数执行带命名参数的插入语句,并通过结果对象获取插入的最后一个自增 ID。

使用事务

事务是一组数据库操作,要么全部成功执行,要么全部回滚。使用 SQLx,你可以轻松地执行事务操作。以下是一个示例:

 func performTransaction(db *sqlx.DB) {
     tx, err := db.Beginx()
     if err != nil {
         log.Fatal(err)
     }
     defer func() {
         if p := recover(); p != nil {
             tx.Rollback()
             panic(p)
         } else if err != nil {
             tx.Rollback()
         } else {
             err = tx.Commit()
         }
     }()
 ​
     // 在事务中执行数据库操作
     // ...
 ​
     // 如果有错误,调用 panic() 触发回滚
     // ...
 ​
     // 如果一切正常,事务会自动提交
     // ...
 }

在这个示例中,我们使用 db.Beginx() 来开始一个新的事务。在事务中的操作要么都成功提交,要么全部回滚。

使用结构体标签

SQLx 支持使用结构体标签来映射数据库字段和 Go 结构体字段。这使得代码更加清晰,减少了手动映射的工作。以下是一个使用结构体标签的示例:

 type Product struct {
     ID       int    `db:"id"`
     Name     string `db:"name"`
     Price    float64 `db:"price"`
     Quantity int    `db:"quantity"`
 }
 ​
 func main() {
     // ...
 ​
     products := []Product{}
     err := db.Select(&products, "SELECT id, name, price, quantity FROM products")
     if err != nil {
         log.Fatal(err)
     }
 ​
     for _, product := range products {
         fmt.Printf("ID: %d, Name: %s, Price: %.2f, Quantity: %d\n", product.ID, product.Name, product.Price, product.Quantity)
     }
 }

在这个示例中,我们使用结构体标签来指定结构体字段与数据库字段之间的映射关系,从而使查询结果能够正确地映射到结构体字段中。

使用查询构建器

SQLx 还提供了查询构建器,可以帮助你以更清晰和类型安全的方式构建复杂的 SQL 查询。以下是一个简单示例:

 import "github.com/jmoiron/sqlx/reflectx"
 ​
 func complexQuery(db *sqlx.DB) {
     query, args, err := sqlx.In("SELECT * FROM products WHERE category IN (?) AND price > ?", []string{"Electronics", "Clothing"}, 100)
     if err != nil {
         log.Fatal(err)
     }
 ​
     query = db.Rebind(query) // 适用于不同数据库驱动
 ​
     rows, err := db.Queryx(query, args...)
     if err != nil {
         log.Fatal(err)
     }
     defer rows.Close()
 ​
     for rows.Next() {
         // 扫描行并处理数据
     }
 }

在这个示例中,我们使用了 sqlx.In() 函数来构建一个包含动态参数的查询,以及 db.Rebind() 来重新绑定查询字符串以适用于不同的数据库驱动。