数据库概述 #

一、数据库选择 #

1.1 常用数据库 #

数据库 类型 适用场景
MySQL 关系型 Web应用、电商
PostgreSQL 关系型 复杂查询、地理信息
SQLite 关系型 小型应用、测试
MongoDB 文档型 灵活数据结构
Redis 键值型 缓存、会话

1.2 ORM框架 #

ORM 说明
GORM 最流行的Go ORM
XORM 轻量级ORM
sqlx 增强的database/sql
sqlc 类型安全的SQL生成

二、数据库连接 #

2.1 原生database/sql #

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

func main() {
    // 连接MySQL
    dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        panic(err)
    }
    defer db.Close()
    
    // 测试连接
    if err := db.Ping(); err != nil {
        panic(err)
    }
    
    r := gin.Default()
    
    r.GET("/users", func(c *gin.Context) {
        rows, err := db.Query("SELECT id, name FROM users")
        if err != nil {
            c.JSON(500, gin.H{"error": err.Error()})
            return
        }
        defer rows.Close()
        
        var users []User
        for rows.Next() {
            var user User
            if err := rows.Scan(&user.ID, &user.Name); err != nil {
                c.JSON(500, gin.H{"error": err.Error()})
                return
            }
            users = append(users, user)
        }
        
        c.JSON(200, users)
    })
    
    r.Run()
}

2.2 使用GORM #

bash
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
go
import (
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

var DB *gorm.DB

func InitDB() {
    dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    
    var err error
    DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        panic(err)
    }
}

func main() {
    InitDB()
    
    r := gin.Default()
    
    r.GET("/users", func(c *gin.Context) {
        var users []User
        if err := DB.Find(&users).Error; err != nil {
            c.JSON(500, gin.H{"error": err.Error()})
            return
        }
        c.JSON(200, users)
    })
    
    r.Run()
}

2.3 PostgreSQL连接 #

bash
go get gorm.io/driver/postgres
go
import (
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

func InitPostgreSQL() {
    dsn := "host=localhost user=gorm password=gorm dbname=gorm port=5432 sslmode=disable TimeZone=Asia/Shanghai"
    
    var err error
    DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        panic(err)
    }
}

2.4 SQLite连接 #

bash
go get gorm.io/driver/sqlite
go
import (
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)

func InitSQLite() {
    var err error
    DB, err = gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    if err != nil {
        panic(err)
    }
}

三、连接池配置 #

3.1 database/sql连接池 #

go
func InitDB() {
    dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        panic(err)
    }
    
    // 最大空闲连接数
    db.SetMaxIdleConns(10)
    
    // 最大打开连接数
    db.SetMaxOpenConns(100)
    
    // 连接最大存活时间
    db.SetConnMaxLifetime(time.Hour)
    
    // 连接最大空闲时间
    db.SetConnMaxIdleTime(10 * time.Minute)
}

3.2 GORM连接池 #

go
func InitDB() {
    dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    
    DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        panic(err)
    }
    
    // 获取底层sql.DB
    sqlDB, err := DB.DB()
    if err != nil {
        panic(err)
    }
    
    // 配置连接池
    sqlDB.SetMaxIdleConns(10)
    sqlDB.SetMaxOpenConns(100)
    sqlDB.SetConnMaxLifetime(time.Hour)
    sqlDB.SetConnMaxIdleTime(10 * time.Minute)
}

3.3 连接池参数说明 #

参数 说明 建议值
MaxIdleConns 最大空闲连接数 10-20
MaxOpenConns 最大打开连接数 100-200
ConnMaxLifetime 连接最大存活时间 30分钟-1小时
ConnMaxIdleTime 连接最大空闲时间 5-10分钟

四、数据库配置管理 #

4.1 配置文件 #

config.yaml:

yaml
database:
  type: mysql
  host: localhost
  port: 3306
  username: root
  password: root
  database: gin_demo
  charset: utf8mb4
  max_idle_conns: 10
  max_open_conns: 100
  conn_max_lifetime: 3600

4.2 配置结构体 #

go
type DatabaseConfig struct {
    Type            string `yaml:"type"`
    Host            string `yaml:"host"`
    Port            int    `yaml:"port"`
    Username        string `yaml:"username"`
    Password        string `yaml:"password"`
    Database        string `yaml:"database"`
    Charset         string `yaml:"charset"`
    MaxIdleConns    int    `yaml:"max_idle_conns"`
    MaxOpenConns    int    `yaml:"max_open_conns"`
    ConnMaxLifetime int    `yaml:"conn_max_lifetime"`
}

func (c *DatabaseConfig) DSN() string {
    return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True&loc=Local",
        c.Username,
        c.Password,
        c.Host,
        c.Port,
        c.Database,
        c.Charset,
    )
}

4.3 初始化数据库 #

go
var DB *gorm.DB

func InitDatabase(config *DatabaseConfig) error {
    var dsn string
    var dialector gorm.Dialector
    
    switch config.Type {
    case "mysql":
        dsn = config.DSN()
        dialector = mysql.Open(dsn)
    case "postgres":
        dsn = fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable TimeZone=Asia/Shanghai",
            config.Host, config.Username, config.Password, config.Database, config.Port)
        dialector = postgres.Open(dsn)
    case "sqlite":
        dialector = sqlite.Open(config.Database)
    default:
        return fmt.Errorf("unsupported database type: %s", config.Type)
    }
    
    var err error
    DB, err = gorm.Open(dialector, &gorm.Config{
        Logger: logger.Default.LogMode(logger.Info),
    })
    if err != nil {
        return err
    }
    
    sqlDB, err := DB.DB()
    if err != nil {
        return err
    }
    
    sqlDB.SetMaxIdleConns(config.MaxIdleConns)
    sqlDB.SetMaxOpenConns(config.MaxOpenConns)
    sqlDB.SetConnMaxLifetime(time.Duration(config.ConnMaxLifetime) * time.Second)
    
    return nil
}

五、数据库封装 #

5.1 数据库工具类 #

go
package database

import (
    "gorm.io/gorm"
)

type Database struct {
    DB *gorm.DB
}

func NewDatabase(db *gorm.DB) *Database {
    return &Database{DB: db}
}

func (d *Database) Transaction(fn func(*gorm.DB) error) error {
    return d.DB.Transaction(fn)
}

func (d *Database) Ping() error {
    sqlDB, err := d.DB.DB()
    if err != nil {
        return err
    }
    return sqlDB.Ping()
}

func (d *Database) Close() error {
    sqlDB, err := d.DB.DB()
    if err != nil {
        return err
    }
    return sqlDB.Close()
}

5.2 依赖注入 #

go
func main() {
    config := LoadConfig()
    
    if err := InitDatabase(&config.Database); err != nil {
        panic(err)
    }
    
    defer func() {
        sqlDB, _ := DB.DB()
        sqlDB.Close()
    }()
    
    r := gin.Default()
    
    // 注入数据库
    r.Use(func(c *gin.Context) {
        c.Set("db", DB)
        c.Next()
    })
    
    r.Run()
}

六、健康检查 #

6.1 数据库健康检查 #

go
func main() {
    r := gin.Default()
    
    r.GET("/health", func(c *gin.Context) {
        sqlDB, err := DB.DB()
        if err != nil {
            c.JSON(500, gin.H{"status": "error", "message": err.Error()})
            return
        }
        
        if err := sqlDB.Ping(); err != nil {
            c.JSON(500, gin.H{"status": "error", "message": err.Error()})
            return
        }
        
        c.JSON(200, gin.H{"status": "ok"})
    })
    
    r.Run()
}

6.2 详细健康检查 #

go
func main() {
    r := gin.Default()
    
    r.GET("/health/detail", func(c *gin.Context) {
        sqlDB, err := DB.DB()
        if err != nil {
            c.JSON(500, gin.H{"status": "error"})
            return
        }
        
        stats := sqlDB.Stats()
        
        c.JSON(200, gin.H{
            "status":          "ok",
            "max_open_conns":  stats.MaxOpenConnections,
            "open_conns":      stats.OpenConnections,
            "in_use":          stats.InUse,
            "idle":            stats.Idle,
            "wait_count":      stats.WaitCount,
            "wait_duration":   stats.WaitDuration.String(),
            "max_idle_closed": stats.MaxIdleClosed,
            "max_lifetime_closed": stats.MaxLifetimeClosed,
        })
    })
    
    r.Run()
}

七、总结 #

7.1 核心要点 #

要点 说明
数据库选择 MySQL、PostgreSQL、SQLite
ORM框架 GORM最常用
连接池 合理配置连接池参数
配置管理 使用配置文件管理

7.2 最佳实践 #

实践 说明
连接池 合理配置连接池
健康检查 提供健康检查接口
错误处理 统一错误处理
资源释放 及时关闭连接

7.3 下一步 #

现在你已经了解了数据库概述,接下来让我们学习 GORM集成,深入了解GORM的使用!

最后更新:2026-03-28