Golang MySQL操作实战

最近在学习Golang操作MySQL数据库,想请教几个实战问题:

  1. 如何用Golang建立MySQL连接池?最佳配置参数有哪些?
  2. 执行SQL查询时,如何处理结果集映射到结构体更高效?
  3. 事务操作有哪些需要注意的坑?比如错误处理和回滚机制
  4. 有没有推荐的ORM库?对比原生SQL各有什么优劣?
  5. 在大并发场景下,数据库操作有哪些性能优化技巧?

希望能分享一些实际项目中的经验,谢谢!

2 回复

使用Go操作MySQL,推荐使用database/sqlgo-sql-driver/mysql。基本步骤:导入驱动、建立连接、执行SQL查询、处理结果。注意使用预处理防SQL注入,及时关闭连接和结果集。

更多关于Golang MySQL操作实战的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang MySQL 操作实战指南

1. 安装驱动

go get -u github.com/go-sql-driver/mysql

2. 基础连接与操作

连接数据库

package main

import (
    "database/sql"
    "fmt"
    "log"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    // 连接字符串格式: "用户名:密码@协议(地址:端口)/数据库名?参数"
    dsn := "user:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True"
    
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // 验证连接
    err = db.Ping()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("数据库连接成功!")
}

创建表

func createTable(db *sql.DB) error {
    query := `
    CREATE TABLE IF NOT EXISTS users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(100) NOT NULL,
        email VARCHAR(100) UNIQUE NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )`
    
    _, err := db.Exec(query)
    return err
}

3. CRUD 操作

插入数据

func insertUser(db *sql.DB, name, email string) (int64, error) {
    result, err := db.Exec(
        "INSERT INTO users (name, email) VALUES (?, ?)",
        name, email,
    )
    if err != nil {
        return 0, err
    }
    
    return result.LastInsertId()
}

查询数据

type User struct {
    ID        int
    Name      string
    Email     string
    CreatedAt time.Time
}

func getUserByID(db *sql.DB, id int) (*User, error) {
    var user User
    err := db.QueryRow(
        "SELECT id, name, email, created_at FROM users WHERE id = ?",
        id,
    ).Scan(&user.ID, &user.Name, &user.Email, &user.CreatedAt)
    
    if err != nil {
        return nil, err
    }
    return &user, nil
}

// 查询多条记录
func getAllUsers(db *sql.DB) ([]User, error) {
    rows, err := db.Query("SELECT id, name, email, created_at FROM users")
    if err != nil {
        return nil, err
    }
    defer rows.Close()
    
    var users []User
    for rows.Next() {
        var user User
        err := rows.Scan(&user.ID, &user.Name, &user.Email, &user.CreatedAt)
        if err != nil {
            return nil, err
        }
        users = append(users, user)
    }
    
    return users, nil
}

更新数据

func updateUserEmail(db *sql.DB, id int, newEmail string) error {
    _, err := db.Exec(
        "UPDATE users SET email = ? WHERE id = ?",
        newEmail, id,
    )
    return err
}

删除数据

func deleteUser(db *sql.DB, id int) error {
    _, err := db.Exec("DELETE FROM users WHERE id = ?", id)
    return err
}

4. 事务处理

func transferMoney(db *sql.DB, fromID, toID int, amount float64) error {
    tx, err := db.Begin()
    if err != nil {
        return err
    }
    
    defer func() {
        if err != nil {
            tx.Rollback()
            return
        }
        err = tx.Commit()
    }()
    
    // 执行多个操作
    _, err = tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, fromID)
    if err != nil {
        return err
    }
    
    _, err = tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, toID)
    if err != nil {
        return err
    }
    
    return nil
}

5. 连接池配置

func initDB() *sql.DB {
    dsn := "user:password@tcp(127.0.0.1:3306)/testdb"
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        log.Fatal(err)
    }
    
    // 配置连接池
    db.SetMaxOpenConns(25)      // 最大连接数
    db.SetMaxIdleConns(10)      // 最大空闲连接数
    db.SetConnMaxLifetime(5 * time.Minute) // 连接最大存活时间
    
    return db
}

最佳实践

  1. 使用预处理语句防止 SQL 注入
  2. 及时关闭 rows 和 statements
  3. 合理配置连接池参数
  4. 使用事务保证数据一致性
  5. 正确处理错误和空值

这个指南涵盖了 Golang 操作 MySQL 的核心功能,可以直接在实际项目中使用。

回到顶部