GORM 支持多种数据库,包括 MySQL、PostgreSQL、SQLite、SQL Server 等。以下是连接不同数据库的方法和注意事项。
连接 MySQL
基本连接
goimport ( "gorm.io/driver/mysql" "gorm.io/gorm" ) 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{})
连接参数说明
user: 数据库用户名password: 数据库密码tcp(127.0.0.1:3306): 主机和端口dbname: 数据库名称charset=utf8mb4: 字符集parseTime=True: 解析时间loc=Local: 时区设置
高级配置
godsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local&timeout=10s&readTimeout=30s&writeTimeout=30s" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ Logger: logger.Default.LogMode(logger.Info), NowFunc: func() time.Time { return time.Now().Local() }, })
连接 PostgreSQL
基本连接
goimport ( "gorm.io/driver/postgres" "gorm.io/gorm" ) dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai" db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
连接参数说明
host: 数据库主机user: 数据库用户名password: 数据库密码dbname: 数据库名称port: 端口号sslmode: SSL 模式TimeZone: 时区设置
使用 URL 格式
godsn := "postgres://gorm:gorm@localhost:9920/gorm?sslmode=disable&timezone=Asia/Shanghai" db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
连接 SQLite
基本连接
goimport ( "gorm.io/driver/sqlite" "gorm.io/gorm" ) db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
内存数据库
godb, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
连接 SQL Server
基本连接
goimport ( "gorm.io/driver/sqlserver" "gorm.io/gorm" ) dsn := "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm" db, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{})
连接池配置
获取底层 SQL DB
gosqlDB, err := db.DB() if err != nil { panic("failed to get database connection") }
配置连接池参数
go// 设置空闲连接池中的最大连接数 sqlDB.SetMaxIdleConns(10) // 设置数据库的最大打开连接数 sqlDB.SetMaxOpenConns(100) // 设置连接可复用的最长时间 sqlDB.SetConnMaxLifetime(time.Hour) // 设置连接最大空闲时间 sqlDB.SetConnMaxIdleTime(10 * time.Minute)
GORM 配置选项
基本配置
godb, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ // 跳过默认事务 SkipDefaultTransaction: true, // 禁用外键约束 DisableForeignKeyConstraintWhenMigrating: true, // 忽略数据错误 IgnoreRelationshipsWhenMigrating: true, })
Logger 配置
goimport "gorm.io/gorm/logger" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ Logger: logger.Default.LogMode(logger.Info), }) // 自定义 Logger newLogger := logger.New( log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ SlowThreshold: time.Second, // 慢查询阈值 LogLevel: logger.Info, // 日志级别 IgnoreRecordNotFoundError: true, // 忽略记录未找到错误 Colorful: true, // 彩色输出 }, ) db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{ Logger: newLogger, })
命名策略配置
goimport "gorm.io/gorm/schema" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ NamingStrategy: schema.NamingStrategy{ SingularTable: true, // 使用单数表名 NoLowerCase: true, // 不转换为小写 }, })
数据库特定配置
MySQL 特定配置
goimport "gorm.io/driver/mysql" db, err := gorm.Open(mysql.New(mysql.Config{ DSN: dsn, DefaultStringSize: 256, // 默认字符串长度 DisableDatetimePrecision: true, // 禁用 datetime 精度 DontSupportRenameIndex: true, // 不支持重命名索引 DontSupportRenameColumn: true, // 不支持重命名列 SkipInitializeWithVersion: false, // 根据版本自动配置 }), &gorm.Config{})
PostgreSQL 特定配置
goimport "gorm.io/driver/postgres" db, err := gorm.Open(postgres.New(postgres.Config{ DSN: dsn, PreferSimpleProtocol: false, // 禁用 prepared statement }), &gorm.Config{})
连接管理最佳实践
1. 使用连接池
gosqlDB, _ := db.DB() sqlDB.SetMaxIdleConns(10) sqlDB.SetMaxOpenConns(100) sqlDB.SetConnMaxLifetime(time.Hour)
2. 测试连接
gosqlDB, _ := db.DB() if err := sqlDB.Ping(); err != nil { panic("failed to connect to database") }
3. 优雅关闭
gosqlDB, _ := db.DB() defer sqlDB.Close()
4. 连接重试
gofunc connectWithRetry(dsn string, maxRetries int) (*gorm.DB, error) { var db *gorm.DB var err error for i := 0; i < maxRetries; i++ { db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err == nil { return db, nil } time.Sleep(time.Second * time.Duration(i+1)) } return nil, err }
环境变量配置
使用环境变量
goimport "os" dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_NAME"), ) db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
多数据库连接
连接多个数据库
go// 主数据库 primaryDB, err := gorm.Open(mysql.Open(primaryDSN), &gorm.Config{}) // 从数据库 replicaDB, err := gorm.Open(mysql.Open(replicaDSN), &gorm.Config{}) // 使用不同的数据库 primaryDB.Create(&user) replicaDB.First(&user, 1)
注意事项
- 连接池大小:根据应用并发量合理设置连接池大小
- 超时设置:设置合理的连接超时和读写超时
- 错误处理:正确处理连接错误和查询错误
- 资源释放:确保在应用退出时关闭数据库连接
- 安全性:不要在代码中硬编码数据库密码
- 监控:监控连接池的使用情况,及时发现问题
常见问题
Q: 如何处理连接超时?
A: 在 DSN 中设置 timeout 参数,或使用 context 设置超时。
Q: 连接池应该设置多大?
A: 根据应用并发量和数据库服务器性能调整,通常 MaxOpenConns 设置为 CPU 核心数的 2-4 倍。
Q: 如何切换数据库?
A: 只需要更换对应的 driver 和 DSN,其他代码基本不需要修改。
Q: 如何处理数据库连接泄漏?
A: 使用 defer 确保连接关闭,监控连接池状态,设置合理的连接生命周期。