Go使用sqlx操作MySQL完整指南

markdown 复制代码
# Go使用sqlx操作MySQL完整指南

## 1. 安装依赖

```bash
go get github.com/go-sql-driver/mysql
go get github.com/jmoiron/sqlx

2. 数据库基础操作

go 复制代码
package main

import (
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

// 定义全局db对象
var db *sqlx.DB

// 用户结构体
type User struct {
    ID       int    `db:"id"`
    Username string `db:"username"`
    Password string `db:"password"`
    Age      int    `db:"age"`
}

// 初始化数据库连接
func initDB() (err error) {
    // 连接数据库
    dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True"
    db, err = sqlx.Connect("mysql", dsn)
    if err != nil {
        return err
    }
    
    // 设置连接池参数
    db.SetMaxOpenConns(100)
    db.SetMaxIdleConns(10)
    return nil
}

// 创建数据库
func createDatabase() error {
    _, err := db.Exec("CREATE DATABASE IF NOT EXISTS test DEFAULT CHARACTER SET utf8mb4")
    return err
}

// 删除数据库
func dropDatabase() error {
    _, err := db.Exec("DROP DATABASE IF EXISTS test")
    return err
}

// 创建表
func createTable() error {
    sql := `
    CREATE TABLE IF NOT EXISTS users(
        id INT PRIMARY KEY AUTO_INCREMENT,
        username VARCHAR(50) NOT NULL UNIQUE,
        password VARCHAR(50) NOT NULL,
        age INT
    )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    `
    _, err := db.Exec(sql)
    return err
}

// 删除表
func dropTable() error {
    _, err := db.Exec("DROP TABLE IF EXISTS users")
    return err
}

// 插入单条数据
func insertUser(user User) error {
    sql := "INSERT INTO users(username, password, age) VALUES (?, ?, ?)"
    _, err := db.Exec(sql, user.Username, user.Password, user.Age)
    return err
}

// 批量插入数据
func batchInsertUsers(users []User) error {
    sql := "INSERT INTO users(username, password, age) VALUES (:username, :password, :age)"
    _, err := db.NamedExec(sql, users)
    return err
}

// 查询单个用户
func getUserByID(id int) (User, error) {
    var user User
    sql := "SELECT * FROM users WHERE id=?"
    err := db.Get(&user, sql, id)
    return user, err
}

// 查询多个用户
func getUsers(age int) ([]User, error) {
    var users []User
    sql := "SELECT * FROM users WHERE age > ?"
    err := db.Select(&users, sql, age)
    return users, err
}

// 更新用户
func updateUser(user User) error {
    sql := "UPDATE users SET password=?, age=? WHERE username=?"
    _, err := db.Exec(sql, user.Password, user.Age, user.Username)
    return err
}

// 删除用户
func deleteUser(id int) error {
    sql := "DELETE FROM users WHERE id=?"
    _, err := db.Exec(sql, id)
    return err
}

func main() {
    // 初始化数据库连接
    if err := initDB(); err != nil {
        fmt.Printf("init db failed, err:%v\n", err)
        return
    }
    defer db.Close()
    
    // 创建数据库
    if err := createDatabase(); err != nil {
        fmt.Printf("create database failed, err:%v\n", err)
        return
    }
    
    // 创建表
    if err := createTable(); err != nil {
        fmt.Printf("create table failed, err:%v\n", err)
        return
    }
    
    // 插入单个用户
    user1 := User{
        Username: "张三",
        Password: "123456",
        Age:      20,
    }
    if err := insertUser(user1); err != nil {
        fmt.Printf("insert user failed, err:%v\n", err)
        return
    }
    
    // 批量插入用户
    users := []User{
        {Username: "李四", Password: "123456", Age: 21},
        {Username: "王五", Password: "123456", Age: 22},
        {Username: "赵六", Password: "123456", Age: 23},
    }
    if err := batchInsertUsers(users); err != nil {
        fmt.Printf("batch insert users failed, err:%v\n", err)
        return
    }
    
    // 查询单个用户
    user, err := getUserByID(1)
    if err != nil {
        fmt.Printf("get user failed, err:%v\n", err)
        return
    }
    fmt.Printf("user:%#v\n", user)
    
    // 查询多个用户
    userList, err := getUsers(20)
    if err != nil {
        fmt.Printf("get users failed, err:%v\n", err)
        return
    }
    fmt.Printf("users:%#v\n", userList)
    
    // 更新用户
    user1.Password = "654321"
    if err := updateUser(user1); err != nil {
        fmt.Printf("update user failed, err:%v\n", err)
        return
    }
    
    // 删除用户
    if err := deleteUser(1); err != nil {
        fmt.Printf("delete user failed, err:%v\n", err)
        return
    }
    
    // 删除表
    if err := dropTable(); err != nil {
        fmt.Printf("drop table failed, err:%v\n", err)
        return
    }
    
    // 删除数据库
    if err := dropDatabase(); err != nil {
        fmt.Printf("drop database failed, err:%v\n", err)
        return
    }
}

3. 事务操作示例

go 复制代码
// 使用事务进行转账
func transfer(fromUsername, toUsername string, amount int) error {
    tx, err := db.Beginx() // 开启事务
    if err != nil {
        return err
    }
    
    // 在事务中执行多个SQL操作
    sql1 := "UPDATE users SET balance = balance - ? WHERE username = ?"
    sql2 := "UPDATE users SET balance = balance + ? WHERE username = ?"
    
    // 执行第一个SQL
    result1, err := tx.Exec(sql1, amount, fromUsername)
    if err != nil {
        tx.Rollback() // 回滚事务
        return err
    }
    
    // 检查影响行数
    rows1, err := result1.RowsAffected()
    if err != nil {
        tx.Rollback()
        return err
    }
    if rows1 != 1 {
        tx.Rollback()
        return fmt.Errorf("转出账户不存在")
    }
    
    // 执行第二个SQL
    result2, err := tx.Exec(sql2, amount, toUsername)
    if err != nil {
        tx.Rollback()
        return err
    }
    
    // 检查影响行数
    rows2, err := result2.RowsAffected()
    if err != nil {
        tx.Rollback()
        return err
    }
    if rows2 != 1 {
        tx.Rollback()
        return fmt.Errorf("转入账户不存在")
    }
    
    // 提交事务
    return tx.Commit()
}

4. 常用查询技巧

4.1 IN查询

go 复制代码
func getUsersByIDs(ids []int) ([]User, error) {
    query, args, err := sqlx.In("SELECT * FROM users WHERE id IN (?)", ids)
    if err != nil {
        return nil, err
    }
    
    query = db.Rebind(query)
    var users []User
    err = db.Select(&users, query, args...)
    return users, err
}

4.2 分页查询

go 复制代码
func getUsersByPage(page, pageSize int) ([]User, error) {
    offset := (page - 1) * pageSize
    sql := "SELECT * FROM users LIMIT ? OFFSET ?"
    var users []User
    err := db.Select(&users, sql, pageSize, offset)
    return users, err
}

4.3 模糊查询

go 复制代码
func searchUsers(keyword string) ([]User, error) {
    sql := "SELECT * FROM users WHERE username LIKE ?"
    var users []User
    err := db.Select(&users, sql, "%"+keyword+"%")
    return users, err
}

5. 注意事项

  1. 始终记得关闭数据库连接
  2. 使用事务时要确保正确处理回滚和提交
  3. 使用预处理语句防止SQL注入
  4. 合理设置连接池参数
  5. 处理所有可能的错误
  6. 使用合适的字段类型和索引优化查询性能

6. 最佳实践

  1. 使用结构体标签映射数据库字段
  2. 统一错误处理
  3. 使用连接池
  4. 合理组织代码结构
  5. 编写单元测试
  6. 记录必要的日志
  7. 定期备份数据库
复制代码
相关推荐
微微%37 分钟前
mysql的安装和使用
数据库·mysql·mysql8安装
OpenAnolis小助手1 小时前
PHP 两个严重漏洞曝光,龙蜥社区 24 小时完成 3 版本修复
开发语言·操作系统·php·龙蜥社区
阿尼卡~2 小时前
VS Code 配置 C 语言开发环境(Windows 10/11):从 GCC 安装到运行、断点调试,一篇搞定
c语言·开发语言·windows
hhhjhl3 小时前
Undici 跨端三方库仓颉适配全流程
java·开发语言·ubuntu
染指11103 小时前
158.Agent-LangGraph-子图(共享状态和不共享状态模式)
开发语言·人工智能·python·ui·agent·agents
wangchunyu1144 小时前
JAVA JVM内存结构与运行时数据区
java·开发语言·jvm
slongzhang_4 小时前
linux 递归删除源码文件|递归删除目录下 *.js,但排除 *.min.js
linux·开发语言·javascript
云和数据.ChenGuang5 小时前
Python 常见特殊方法详解:__new__、__init__、__del__、__str__、__repr__ 与 __getattribute__
开发语言·人工智能·python·1024程序员节
十年程序梦5 小时前
2026最新国内省市区县表,mysql表格
mysql
xyouyuweizhu5 小时前
字节流与字符流:Java IO 的两条主线该怎么选
java·开发语言·python