Go语言中的数据库操作大全从SQL到ORM

 更新时间:2026年04月21日 10:22:25   作者:王码码2035哦  
本文将详细介绍Go语言中的数据库操作,从基础的SQL操作到高级的ORM框架,帮助你构建更加高效、可靠的数据库应用,感兴趣的朋友一起看看吧

1. 数据库操作的重要性

在现代应用开发中,数据库是存储和管理数据的核心组件。Go语言提供了多种方式来操作数据库,从原生SQL到ORM框架,满足不同场景的需求。本文将详细介绍Go语言中的数据库操作,从基础的SQL操作到高级的ORM框架,帮助你构建更加高效、可靠的数据库应用。

2. 标准库database/sql

2.1 基本使用

Go语言的标准库database/sql提供了数据库操作的基础功能,它是一个抽象层,支持多种数据库驱动。

package main
import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
)
func main() {
    db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/database")
    if err != nil {
        fmt.Printf("Error opening database: %v\n", err)
        return
    }
    defer db.Close()
    // 测试连接
    err = db.Ping()
    if err != nil {
        fmt.Printf("Error pinging database: %v\n", err)
        return
    }
    fmt.Println("Connected to database successfully")
}

2.2 执行SQL查询

你可以使用db.Query()db.QueryRow()来执行SQL查询。

// 查询多个记录
rows, err := db.Query("SELECT id, name FROM users WHERE age > ?", 18)
if err != nil {
    fmt.Printf("Error querying database: %v\n", err)
    return
}
defer rows.Close()
for rows.Next() {
    var id int
    var name string
    err := rows.Scan(&id, &name)
    if err != nil {
        fmt.Printf("Error scanning row: %v\n", err)
        return
    }
    fmt.Printf("ID: %d, Name: %s\n", id, name)
}
// 查询单个记录
var name string
err = db.QueryRow("SELECT name FROM users WHERE id = ?", 1).Scan(&name)
if err != nil {
    fmt.Printf("Error querying row: %v\n", err)
    return
}
fmt.Printf("Name: %s\n", name)

2.3 执行SQL更新

你可以使用db.Exec()来执行SQL更新操作。

result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)", "John", 30)
if err != nil {
    fmt.Printf("Error inserting record: %v\n", err)
    return
}
id, err := result.LastInsertId()
if err != nil {
    fmt.Printf("Error getting last insert id: %v\n", err)
    return
}
rowsAffected, err := result.RowsAffected()
if err != nil {
    fmt.Printf("Error getting rows affected: %v\n", err)
    return
}
fmt.Printf("Inserted record with ID: %d, rows affected: %d\n", id, rowsAffected)

3. 数据库驱动

3.1 常用数据库驱动

Go语言支持多种数据库驱动,如:

  • MySQL: github.com/go-sql-driver/mysql
  • PostgreSQL: github.com/lib/pq
  • SQLite: github.com/mattn/go-sqlite3
  • Oracle: github.com/sijms/go-ora/v2
  • SQL Server: github.com/denisenkom/go-mssqldb

3.2 驱动安装

你可以使用go get命令安装数据库驱动:

go get github.com/go-sql-driver/mysql
go get github.com/lib/pq
go get github.com/mattn/go-sqlite3

4. ORM框架

4.1 常用ORM框架

Go语言中有多个流行的ORM框架,如:

  • GORM: gorm.io/gorm
  • XORM: xorm.io/xorm
  • SQLx: github.com/jmoiron/sqlx
  • Ent: entgo.io/ent

4.2 GORM

GORM是Go语言中最流行的ORM框架之一,提供了丰富的功能。

package main
import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)
type User struct {
    ID   uint
    Name string
    Age  int
}
func main() {
    dsn := "username:password@tcp(localhost:3306)/database?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        fmt.Printf("Error connecting to database: %v\n", err)
        return
    }
    // 自动迁移表结构
    err = db.AutoMigrate(&User{})
    if err != nil {
        fmt.Printf("Error migrating table: %v\n", err)
        return
    }
    // 创建记录
    user := User{Name: "John", Age: 30}
    result := db.Create(&user)
    if result.Error != nil {
        fmt.Printf("Error creating user: %v\n", result.Error)
        return
    }
    fmt.Printf("Created user with ID: %d\n", user.ID)
    // 查询记录
    var foundUser User
    result = db.First(&foundUser, user.ID)
    if result.Error != nil {
        fmt.Printf("Error finding user: %v\n", result.Error)
        return
    }
    fmt.Printf("Found user: ID=%d, Name=%s, Age=%d\n", foundUser.ID, foundUser.Name, foundUser.Age)
    // 更新记录
    result = db.Model(&foundUser).Update("Age", 31)
    if result.Error != nil {
        fmt.Printf("Error updating user: %v\n", result.Error)
        return
    }
    fmt.Println("Updated user successfully")
    // 删除记录
    result = db.Delete(&foundUser)
    if result.Error != nil {
        fmt.Printf("Error deleting user: %v\n", result.Error)
        return
    }
    fmt.Println("Deleted user successfully")
}

4.3 SQLx

SQLx是一个轻量级的ORM框架,它扩展了标准库database/sql,提供了更多便利的功能。

package main
import (
    "fmt"
    "github.com/jmoiron/sqlx"
    _ "github.com/go-sql-driver/mysql"
)
type User struct {
    ID   int    `db:"id"`
    Name string `db:"name"`
    Age  int    `db:"age"`
}
func main() {
    db, err := sqlx.Connect("mysql", "username:password@tcp(localhost:3306)/database")
    if err != nil {
        fmt.Printf("Error connecting to database: %v\n", err)
        return
    }
    defer db.Close()
    // 查询多个记录
    var users []User
    err = db.Select(&users, "SELECT id, name, age FROM users WHERE age > ?", 18)
    if err != nil {
        fmt.Printf("Error querying users: %v\n", err)
        return
    }
    for _, user := range users {
        fmt.Printf("ID: %d, Name: %s, Age: %d\n", user.ID, user.Name, user.Age)
    }
    // 查询单个记录
    var user User
    err = db.Get(&user, "SELECT id, name, age FROM users WHERE id = ?", 1)
    if err != nil {
        fmt.Printf("Error querying user: %v\n", err)
        return
    }
    fmt.Printf("User: ID=%d, Name=%s, Age=%d\n", user.ID, user.Name, user.Age)
}

5. 数据库连接池

5.1 连接池配置

标准库database/sql默认使用连接池,你可以配置连接池的参数。

package main
import (
    "database/sql"
    "fmt"
    "time"
    _ "github.com/go-sql-driver/mysql"
)
func main() {
    db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/database")
    if err != nil {
        fmt.Printf("Error opening database: %v\n", err)
        return
    }
    defer db.Close()
    // 配置连接池
    db.SetMaxOpenConns(25)           // 最大打开连接数
    db.SetMaxIdleConns(5)            // 最大空闲连接数
    db.SetConnMaxLifetime(5 * time.Minute) // 连接最大生命周期
    // 测试连接
    err = db.Ping()
    if err != nil {
        fmt.Printf("Error pinging database: %v\n", err)
        return
    }
    fmt.Println("Connected to database successfully")
}

5.2 连接池最佳实践

  • 设置合理的最大打开连接数,避免连接过多导致数据库压力过大
  • 设置合理的最大空闲连接数,提高连接重用率
  • 设置连接最大生命周期,避免使用过期连接

6. 事务处理

6.1 标准库事务

你可以使用db.Begin()来开始一个事务。

package main
import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
)
func main() {
    db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/database")
    if err != nil {
        fmt.Printf("Error opening database: %v\n", err)
        return
    }
    defer db.Close()
    // 开始事务
    tx, err := db.Begin()
    if err != nil {
        fmt.Printf("Error beginning transaction: %v\n", err)
        return
    }
    // 执行SQL操作
    _, err = tx.Exec("INSERT INTO users (name, age) VALUES (?, ?)", "John", 30)
    if err != nil {
        tx.Rollback()
        fmt.Printf("Error inserting record: %v\n", err)
        return
    }
    _, err = tx.Exec("UPDATE users SET age = ? WHERE name = ?", 31, "John")
    if err != nil {
        tx.Rollback()
        fmt.Printf("Error updating record: %v\n", err)
        return
    }
    // 提交事务
    err = tx.Commit()
    if err != nil {
        fmt.Printf("Error committing transaction: %v\n", err)
        return
    }
    fmt.Println("Transaction committed successfully")
}

6.2 GORM事务

GORM提供了更加便捷的事务处理方式。

package main
import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)
type User struct {
    ID   uint
    Name string
    Age  int
}
func main() {
    dsn := "username:password@tcp(localhost:3306)/database?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        fmt.Printf("Error connecting to database: %v\n", err)
        return
    }
    // 自动迁移表结构
    err = db.AutoMigrate(&User{})
    if err != nil {
        fmt.Printf("Error migrating table: %v\n", err)
        return
    }
    // 事务处理
    err = db.Transaction(func(tx *gorm.DB) error {
        // 创建记录
        user := User{Name: "John", Age: 30}
        if err := tx.Create(&user).Error; err != nil {
            return err
        }
        // 更新记录
        if err := tx.Model(&user).Update("Age", 31).Error; err != nil {
            return err
        }
        return nil
    })
    if err != nil {
        fmt.Printf("Error in transaction: %v\n", err)
        return
    }
    fmt.Println("Transaction completed successfully")
}

7. 数据库迁移

7.1 GORM迁移

GORM提供了自动迁移功能,可以根据结构体定义自动创建和更新表结构。

package main
import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)
type User struct {
    ID   uint
    Name string
    Age  int
}
type Product struct {
    ID    uint
    Name  string
    Price float64
}
func main() {
    dsn := "username:password@tcp(localhost:3306)/database?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        fmt.Printf("Error connecting to database: %v\n", err)
        return
    }
    // 自动迁移表结构
    err = db.AutoMigrate(&User{}, &Product{})
    if err != nil {
        fmt.Printf("Error migrating tables: %v\n", err)
        return
    }
    fmt.Println("Migration completed successfully")
}

7.2 手动迁移

你也可以使用SQL语句手动进行数据库迁移。

package main
import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
)
func main() {
    db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/database")
    if err != nil {
        fmt.Printf("Error opening database: %v\n", err)
        return
    }
    defer db.Close()
    // 创建表
    _, err = db.Exec(`
        CREATE TABLE IF NOT EXISTS users (
            id INT AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(255) NOT NULL,
            age INT NOT NULL
        )
    `)
    if err != nil {
        fmt.Printf("Error creating table: %v\n", err)
        return
    }
    fmt.Println("Table created successfully")
}

8. 性能优化

8.1 索引优化

合理使用索引可以提高查询性能。

// 在GORM中添加索引
type User struct {
    ID   uint
    Name string `gorm:"index"`
    Age  int    `gorm:"index"`
}

8.2 批量操作

批量操作可以减少数据库交互次数,提高性能。

// 批量插入
users := []User{
    {Name: "John", Age: 30},
    {Name: "Jane", Age: 25},
    {Name: "Bob", Age: 35},
}
db.Create(&users)
// 批量更新
db.Model(&User{}).Where("age > ?", 30).Update("age", gorm.Expr("age + ?", 1))

8.3 预编译语句

预编译语句可以提高SQL执行效率。

// 预编译查询
stmt, err := db.Prepare("SELECT id, name FROM users WHERE age > ?")
if err != nil {
    fmt.Printf("Error preparing statement: %v\n", err)
    return
}
defer stmt.Close()
rows, err := stmt.Query(18)
// 处理结果...

9. 常见问题与解决方案

9.1 连接泄漏

问题:数据库连接没有正确关闭,导致连接泄漏

解决方案:使用defer db.Close()确保连接正确关闭

db, err := sql.Open("mysql", "dsn")
if err != nil {
    return
}
defer db.Close()

9.2 事务未提交或回滚

问题:事务开始后没有提交或回滚,导致锁表

解决方案:使用defer确保事务最终会提交或回滚

tx, err := db.Begin()
if err != nil {
    return
}
defer func() {
    if err != nil {
        tx.Rollback()
        return
    }
    err = tx.Commit()
}()
// 执行事务操作...

9.3 SQL注入

问题:使用字符串拼接SQL语句,导致SQL注入

解决方案:使用参数化查询

// 错误做法
name := "John'; DROP TABLE users; --"
query := "SELECT * FROM users WHERE name = '" + name + "'"
// 正确做法
query := "SELECT * FROM users WHERE name = ?"
rows, err := db.Query(query, name)

10. 总结

数据库操作是Go语言开发中不可或缺的一部分。通过本文的介绍,你应该了解了:

  • 如何使用标准库database/sql进行数据库操作
  • 如何使用ORM框架如GORM和SQLx
  • 如何配置数据库连接池
  • 如何处理事务
  • 如何进行数据库迁移
  • 如何优化数据库性能

通过选择合适的数据库操作方式和最佳实践,你可以构建更加高效、可靠的数据库应用,为用户提供更好的体验。

11. 代码示例

11.1 完整的数据库操作示例

package main
import (
    "database/sql"
    "fmt"
    "time"
    _ "github.com/go-sql-driver/mysql"
)
type User struct {
    ID   int
    Name string
    Age  int
}
func main() {
    // 连接数据库
    db, err := sql.Open("mysql", "username:password@tcp(localhost:3306)/database")
    if err != nil {
        fmt.Printf("Error opening database: %v\n", err)
        return
    }
    defer db.Close()
    // 配置连接池
    db.SetMaxOpenConns(25)
    db.SetMaxIdleConns(5)
    db.SetConnMaxLifetime(5 * time.Minute)
    // 测试连接
    err = db.Ping()
    if err != nil {
        fmt.Printf("Error pinging database: %v\n", err)
        return
    }
    fmt.Println("Connected to database successfully")
    // 创建表
    _, err = db.Exec(`
        CREATE TABLE IF NOT EXISTS users (
            id INT AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(255) NOT NULL,
            age INT NOT NULL
        )
    `)
    if err != nil {
        fmt.Printf("Error creating table: %v\n", err)
        return
    }
    // 插入记录
    result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)", "John", 30)
    if err != nil {
        fmt.Printf("Error inserting record: %v\n", err)
        return
    }
    id, err := result.LastInsertId()
    if err != nil {
        fmt.Printf("Error getting last insert id: %v\n", err)
        return
    }
    fmt.Printf("Inserted record with ID: %d\n", id)
    // 查询记录
    var user User
    err = db.QueryRow("SELECT id, name, age FROM users WHERE id = ?", id).Scan(&user.ID, &user.Name, &user.Age)
    if err != nil {
        fmt.Printf("Error querying record: %v\n", err)
        return
    }
    fmt.Printf("Found user: ID=%d, Name=%s, Age=%d\n", user.ID, user.Name, user.Age)
    // 更新记录
    _, err = db.Exec("UPDATE users SET age = ? WHERE id = ?", 31, id)
    if err != nil {
        fmt.Printf("Error updating record: %v\n", err)
        return
    }
    fmt.Println("Updated record successfully")
    // 删除记录
    _, err = db.Exec("DELETE FROM users WHERE id = ?", id)
    if err != nil {
        fmt.Printf("Error deleting record: %v\n", err)
        return
    }
    fmt.Println("Deleted record successfully")
}

11.2 使用GORM的完整示例

package main
import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)
type User struct {
    ID   uint
    Name string
    Age  int
}
func main() {
    // 连接数据库
    dsn := "username:password@tcp(localhost:3306)/database?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        fmt.Printf("Error connecting to database: %v\n", err)
        return
    }
    // 自动迁移表结构
    err = db.AutoMigrate(&User{})
    if err != nil {
        fmt.Printf("Error migrating table: %v\n", err)
        return
    }
    // 创建记录
    user := User{Name: "John", Age: 30}
    result := db.Create(&user)
    if result.Error != nil {
        fmt.Printf("Error creating user: %v\n", result.Error)
        return
    }
    fmt.Printf("Created user with ID: %d\n", user.ID)
    // 查询记录
    var foundUser User
    result = db.First(&foundUser, user.ID)
    if result.Error != nil {
        fmt.Printf("Error finding user: %v\n", result.Error)
        return
    }
    fmt.Printf("Found user: ID=%d, Name=%s, Age=%d\n", foundUser.ID, foundUser.Name, foundUser.Age)
    // 更新记录
    result = db.Model(&foundUser).Update("Age", 31)
    if result.Error != nil {
        fmt.Printf("Error updating user: %v\n", result.Error)
        return
    }
    fmt.Println("Updated user successfully")
    // 删除记录
    result = db.Delete(&foundUser)
    if result.Error != nil {
        fmt.Printf("Error deleting user: %v\n", result.Error)
        return
    }
    fmt.Println("Deleted user successfully")
}

12. 进一步学习资源

通过不断学习和实践,你将能够构建更加高效、可靠的数据库应用,为你的Go项目增添强大的数据存储和管理能力。

到此这篇关于Go语言中的数据库操作大全从SQL到ORM的文章就介绍到这了,更多相关go数据库操作从sql到orm内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go语言包管理模式示例分析

    Go语言包管理模式示例分析

    这篇文章主要为大家介绍了Go语言包管理模式示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • Golang中Gin框架中如何定义路由详解

    Golang中Gin框架中如何定义路由详解

    Gin是一个用Go语言编写的Web框架,具有高性能和易于使用的特点,本文将结合实际案例,详细介绍Gin框架的路由用法,有需要的小伙伴可以参考下
    2024-10-10
  • Go搭建高效的Gin Web目录结构

    Go搭建高效的Gin Web目录结构

    本文主要介绍了Go搭建高效的Gin Web目录结构,构建一个既高效又便于管理的项目架构,助力开发者打造既快速响应又易于维护的Web应用程序,感兴趣的可以了解一下
    2025-08-08
  • Go语言中interface语法与使用详解

    Go语言中interface语法与使用详解

    Go语言里面设计最精妙的应该算interface,它让面向对象,内容组织实现非常的方便,下面这篇文章主要给大家介绍了关于Go语言中interface语法与使用的相关资料,需要的朋友可以参考下
    2022-07-07
  • Go语言中的Slice学习总结

    Go语言中的Slice学习总结

    这篇文章主要介绍了Go语言中的Slice学习总结,本文讲解了Slice的定义、Slice的长度和容量、Slice是引用类型、Slice引用传递发生“意外”等内容,需要的朋友可以参考下
    2014-11-11
  • 详解Go如何优雅的对时间进行格式化

    详解Go如何优雅的对时间进行格式化

    这篇文章主要为大家详细介绍了Go语言中是如何优雅的对时间进行格式化的,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-06-06
  • go 判断两个 slice/struct/map 是否相等的实例

    go 判断两个 slice/struct/map 是否相等的实例

    这篇文章主要介绍了go 判断两个 slice/struct/map 是否相等的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • golang中的依赖注入之wire的使用

    golang中的依赖注入之wire的使用

    wire是Google开源的一个依赖注入工具,它是一个代码生成器,本文就来介绍一下golang中的依赖注入之wire的使用,具有一定的参考价值,感兴趣的可以了解一下
    2026-02-02
  • GO web 数据库预处理的实现

    GO web 数据库预处理的实现

    本文主要介绍了GO web 数据库预处理的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • Go语言中切片展开操作符的实现示例

    Go语言中切片展开操作符的实现示例

    在Go语言编程中,我们经常会遇到处理多维切片数据的场景,今天我们来深入探讨一个非常实用但容易被忽视的语法特性-切片展开操作符,感兴趣的可以了解一下
    2025-10-10

最新评论