SQL语言怎样通过Go语言操作数据库

来源:IPIPP.com作者:头衔:全栈工程师
导读:本期聚焦于小伙伴创作的《SQL语言怎样通过Go语言操作数据库》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《SQL语言怎样通过Go语言操作数据库》有用,将其分享出去将是对创作者最好的鼓励。

在Go语言开发中,操作数据库是常见需求,通过标准库的database/sql包配合对应数据库的驱动,就可以方便地执行SQL语言完成各类数据操作。

SQL语言怎样通过Go语言操作数据库

环境准备

首先需要安装对应数据库的驱动,这里以常用的MySQL为例,执行以下命令安装驱动:

// 安装MySQL驱动
go get -u github.com/go-sql-driver/mysql

建立数据库连接

使用database/sql包的Open函数建立连接,第一个参数是驱动名称,第二个是连接字符串,连接字符串需要包含用户名、密码、数据库地址和库名等信息。

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql" // 匿名导入驱动,触发驱动的init函数注册
)

func main() {
    // 连接字符串格式:用户名:密码@tcp(数据库地址:端口)/数据库名?参数
    dsn := "root:123456@tcp(127.0.0.1:3306)/test_db?charset=utf8mb4"
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        fmt.Printf("数据库连接失败:%v\n", err)
        return
    }
    // 验证连接是否有效
    err = db.Ping()
    if err != nil {
        fmt.Printf("数据库连接验证失败:%v\n", err)
        return
    }
    fmt.Println("数据库连接成功")
    defer db.Close() // 程序结束时关闭连接
}

执行SQL语句操作数据

执行增删改操作

对于INSERT、UPDATE、DELETE这类不返回结果集的SQL语句,使用Exec方法执行,建议始终使用参数化查询避免SQL注入问题。

func insertData(db *sql.DB) {
    // 参数化查询,?是占位符,对应后面的参数
    sqlStr := "INSERT INTO user (name, age) VALUES (?, ?)"
    result, err := db.Exec(sqlStr, "张三", 25)
    if err != nil {
        fmt.Printf("插入数据失败:%v\n", err)
        return
    }
    // 获取插入的自增ID
    lastId, err := result.LastInsertId()
    if err != nil {
        fmt.Printf("获取自增ID失败:%v\n", err)
        return
    }
    // 获取受影响的行数
    rowsAffected, err := result.RowsAffected()
    if err != nil {
        fmt.Printf("获取受影响行数失败:%v\n", err)
        return
    }
    fmt.Printf("插入成功,自增ID:%d,受影响行数:%d\n", lastId, rowsAffected)
}

查询单条数据

查询单条数据使用QueryRow方法,通过Scan方法将查询结果映射到变量中。

func querySingle(db *sql.DB) {
    var id int
    var name string
    var age int
    sqlStr := "SELECT id, name, age FROM user WHERE id = ?"
    // QueryRow返回的是*sql.Row,直接调用Scan方法
    err := db.QueryRow(sqlStr, 1).Scan(&id, &name, &age)
    if err != nil {
        fmt.Printf("查询单条数据失败:%v\n", err)
        return
    }
    fmt.Printf("查询结果:id=%d, name=%s, age=%d\n", id, name, age)
}

查询多条数据

查询多条数据使用Query方法,通过遍历返回的*sql.Rows获取每一条数据,最后要关闭Rows释放资源。

func queryMulti(db *sql.DB) {
    sqlStr := "SELECT id, name, age FROM user WHERE age > ?"
    rows, err := db.Query(sqlStr, 20)
    if err != nil {
        fmt.Printf("查询多条数据失败:%v\n", err)
        return
    }
    defer rows.Close() // 必须关闭,否则会占用连接
    for rows.Next() {
        var id int
        var name string
        var age int
        err := rows.Scan(&id, &name, &age)
        if err != nil {
            fmt.Printf("解析行数据失败:%v\n", err)
            return
        }
        fmt.Printf("id=%d, name=%s, age=%d\n", id, name, age)
    }
    // 检查遍历过程中是否有错误
    if err = rows.Err(); err != nil {
        fmt.Printf("遍历行数据错误:%v\n", err)
    }
}

事务处理

当需要执行多个关联操作时,使用事务保证操作的原子性,要么全部成功,要么全部失败回滚。

func transactionDemo(db *sql.DB) {
    // 开启事务
    tx, err := db.Begin()
    if err != nil {
        fmt.Printf("开启事务失败:%v\n", err)
        return
    }
    // 事务执行失败时的回滚逻辑
    defer func() {
        if p := recover(); p != nil {
            tx.Rollback()
            panic(p)
        } else if err != nil {
            tx.Rollback()
        }
    }()
    // 执行事务内的第一个操作
    _, err = tx.Exec("UPDATE user SET age = age + 1 WHERE id = ?", 1)
    if err != nil {
        fmt.Printf("事务操作1失败:%v\n", err)
        return
    }
    // 执行事务内的第二个操作
    _, err = tx.Exec("UPDATE user SET age = age - 1 WHERE id = ?", 2)
    if err != nil {
        fmt.Printf("事务操作2失败:%v\n", err)
        return
    }
    // 提交事务
    err = tx.Commit()
    if err != nil {
        fmt.Printf("提交事务失败:%v\n", err)
        return
    }
    fmt.Println("事务提交成功")
}

连接池配置

database/sql内置了连接池,我们可以通过以下方法配置连接池参数,优化数据库操作的性能。

func setPoolConfig(db *sql.DB) {
    // 设置连接池最大打开连接数,默认无限制
    db.SetMaxOpenConns(10)
    // 设置连接池最大空闲连接数,默认2
    db.SetMaxIdleConns(5)
    // 设置连接可复用的最大时间,超过该时间连接会被关闭
    db.SetConnMaxLifetime(time.Hour)
}

注意事项

  • 所有的查询结果Rows或者Row使用完毕后,要及时调用Close方法释放资源,避免连接泄露
  • 执行SQL语句时优先使用参数化查询,不要直接拼接SQL字符串,防止SQL注入攻击
  • 驱动使用匿名导入的方式,因为只需要触发驱动的init函数完成注册,不需要直接使用驱动包的其他导出内容
  • 连接字符串中的参数要根据实际数据库的配置调整,比如字符集、时区等

SQLGo语言database/sql数据库驱动MySQL修改时间:2026-05-27 23:26:30

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。