数据库概述 #
一、数据库选择 #
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