Golang数据库SQL操作

在使用Golang进行SQL数据库操作时,如何正确管理数据库连接以避免资源泄露?具体应该在哪里调用db.Close()?在Web服务中,是每个请求都创建关闭连接好,还是全局维护一个连接池更合适?如果使用连接池,如何配置合理的最大连接数和空闲连接数?

2 回复

在Golang中,使用database/sql包进行数据库操作。首先导入驱动(如github.com/go-sql-driver/mysql),然后通过sql.Open()建立连接。使用db.Query()执行查询,db.Exec()执行增删改。务必处理错误并调用rows.Close()。推荐使用预编译语句防SQL注入。

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


在Go语言中,使用标准库 database/sql 进行数据库操作,通常配合特定数据库驱动(如MySQL的 github.com/go-sql-driver/mysql)。以下是基本操作步骤和示例代码:

1. 安装驱动

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

2. 连接数据库

package main

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

func main() {
    // 数据源名称格式: "用户名:密码@协议(地址:端口)/数据库名"
    db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/testdb")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // 验证连接
    err = db.Ping()
    if err != nil {
        log.Fatal("数据库连接失败:", err)
    }
    log.Println("数据库连接成功")
}

3. 执行查询

type User struct {
    ID   int
    Name string
}

// 查询单条记录
func queryUser(db *sql.DB, id int) (*User, error) {
    var user User
    err := db.QueryRow("SELECT id, name FROM users WHERE id = ?", id).Scan(&user.ID, &user.Name)
    if err != nil {
        return nil, err
    }
    return &user, nil
}

// 查询多条记录
func queryUsers(db *sql.DB) ([]User, error) {
    rows, err := db.Query("SELECT id, name FROM users")
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    var users []User
    for rows.Next() {
        var user User
        if err := rows.Scan(&user.ID, &user.Name); err != nil {
            return nil, err
        }
        users = append(users, user)
    }
    return users, nil
}

4. 执行写入操作

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

// 更新数据
func updateUser(db *sql.DB, id int, name string) error {
    _, err := db.Exec("UPDATE users SET name = ? WHERE id = ?", name, id)
    return err
}

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

5. 事务处理

func transferMoney(db *sql.DB, from, to int, amount float64) error {
    tx, err := db.Begin()
    if err != nil {
        return err
    }

    // 执行转账操作
    _, err = tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, from)
    if err != nil {
        tx.Rollback()
        return err
    }

    _, err = tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, to)
    if err != nil {
        tx.Rollback()
        return err
    }

    return tx.Commit()
}

关键要点:

  1. 使用 sql.Open() 初始化连接(实际连接在需要时建立)
  2. 始终检查错误并处理 defer rows.Close()
  3. 使用预处理语句防止SQL注入
  4. 事务操作确保数据一致性
  5. 连接池由 database/sql 自动管理

建议使用结构体标签或ORM库(如GORM)简化复杂操作,但理解原生SQL操作对性能优化和问题排查很重要。

回到顶部