GORM 如何连接不同的数据库?
GORM 支持多种数据库,包括 MySQL、PostgreSQL、SQLite、SQL Server 等。以下是连接不同数据库的方法和注意事项。连接 MySQL基本连接import ( "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: 时区设置高级配置dsn := "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基本连接import ( "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 格式dsn := "postgres://gorm:gorm@localhost:9920/gorm?sslmode=disable&timezone=Asia/Shanghai"db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})连接 SQLite基本连接import ( "gorm.io/driver/sqlite" "gorm.io/gorm")db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})内存数据库db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})连接 SQL Server基本连接import ( "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 DBsqlDB, err := db.DB()if err != nil { panic("failed to get database connection")}配置连接池参数// 设置空闲连接池中的最大连接数sqlDB.SetMaxIdleConns(10)// 设置数据库的最大打开连接数sqlDB.SetMaxOpenConns(100)// 设置连接可复用的最长时间sqlDB.SetConnMaxLifetime(time.Hour)// 设置连接最大空闲时间sqlDB.SetConnMaxIdleTime(10 * time.Minute)GORM 配置选项基本配置db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ // 跳过默认事务 SkipDefaultTransaction: true, // 禁用外键约束 DisableForeignKeyConstraintWhenMigrating: true, // 忽略数据错误 IgnoreRelationshipsWhenMigrating: true,})Logger 配置import "gorm.io/gorm/logger"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ Logger: logger.Default.LogMode(logger.Info),})// 自定义 LoggernewLogger := 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,})命名策略配置import "gorm.io/gorm/schema"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ NamingStrategy: schema.NamingStrategy{ SingularTable: true, // 使用单数表名 NoLowerCase: true, // 不转换为小写 },})数据库特定配置MySQL 特定配置import "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 特定配置import "gorm.io/driver/postgres"db, err := gorm.Open(postgres.New(postgres.Config{ DSN: dsn, PreferSimpleProtocol: false, // 禁用 prepared statement}), &gorm.Config{})连接管理最佳实践1. 使用连接池sqlDB, _ := db.DB()sqlDB.SetMaxIdleConns(10)sqlDB.SetMaxOpenConns(100)sqlDB.SetConnMaxLifetime(time.Hour)2. 测试连接sqlDB, _ := db.DB()if err := sqlDB.Ping(); err != nil { panic("failed to connect to database")}3. 优雅关闭sqlDB, _ := db.DB()defer sqlDB.Close()4. 连接重试func 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}环境变量配置使用环境变量import "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{})多数据库连接连接多个数据库// 主数据库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 确保连接关闭,监控连接池状态,设置合理的连接生命周期。