GORM的下载与安装
首先GORM 升级到 V2 以后项目组织发生了变更从 github.com/jinzhu/gorm 变成了 gorm.io/gorm 安装步骤也会跟之前的V1版本有些不同
我们先来安装GORM,边安装边说。
go get -u gorm.io/gorm
GORM 在V1 版本中各个数据库的驱动是和整个软件包绑定在一起的,所以下载安装一次就行了,但是到了V2之后每种数据库单独提供了驱动,我们使用的是MySQL,所以先把MySQL的驱动安装一下
go get -u "gorm.io/driver/mysql"
如果你的数据库里用了多数据源,那么你需要把项目用到的每个数据库类型的驱动都先安装上,假如说项目中还使用了 postgres 那么在初始化GORM前也需要把 postgres 的驱动下载下来。
go get -u "gorm.io/driver/postgres"
之所以安装这个驱动呢,是因为两个版本在初始化数据看连接时的Open 方法有了调整
// V1
func Open(dialect string, args ...interface{}) (db *DB, err error) {}
// V2
func Open(dialector Dialector, opts ...Option) (db *DB, err error) {}
V1 版本我们直接传一个数据库类型的字符串就行了
db, err := gorm.Open("mysql", "root:pass@tcp(xxx)/db_name")
if err != nil {
panic(err)
}
而V2版本需要用到我们刚才安装的驱动
db, err := gorm.Open(
mysql.Open("root:pass@tcp(xxx)/db_name),
&gorm.Config{},
)
初始化GORM
安装完驱动后先不着急去初始化GORM,前面的章节《Go 项目配置的定制化及一体化打包方案》我们给项目做好了配置管理,所以我们得先把配置文件进行一些调整,打开我们的config/application.dev.yaml 文件,添加一些Database相关的配置
database:
type: mysql
master:
dsn: root:superpass@tcp(localhost:30306)/go_mall?xxx...
maxopen: 100
maxidle: 10
maxlifetime: 300000000000
slave:
dsn: root:superpass@tcp(localhost:30306)/go_mall?xxx...
maxopen: 100
maxidle: 10
maxlifetime: 300000000000
这里我们配置了主从两个数据库连接的配置,因为我们项目里暂时用不到主从分离,所以就先把主库和从库设置的一样,等实际开发用到主从实例了再去进行相应的修改。这里的参数等到下面初始化GORM的时候再去细讲。
接下来我们在 dal/dao/gorminit.go 中写一个initDB的自定义函数,把用Database配置来初始化GORM DB连接的这部操作抽象提炼到一起
func initDB(option config.DbConnectOption) *gorm.DB {
db, err := gorm.Open(mysql.Open(option.DSN), &gorm.Config{})
if err != nil {
panic(err)
}
sqlDb, _ := db.DB()
sqlDb.SetMaxOpenConns(option.MaxOpenConn)
sqlDb.SetMaxIdleConns(option.MaxIdleConn)
sqlDb.SetConnMaxLifetime(option.MaxLifeTime)
if err = sqlDb.Ping(); err != nil {
panic(err)
}
return db}
生产环境GORM必须设置的连接参数
GORM 使用的是Go的 database/sql 来维护的连接池,这里解释一下创建GORM DB连接时用到的这些参数,我们在配置文件里指定的maxidle、maxopen、maxlifetime 分别传递给了GORM DB的下面三个方法,这三个方法在生产环境时一定要记得设置
- SetMaxIdleConns(10) 设置最大空闲连接数为10个。
- SetMaxOpenConns(100) 设置可打开的最大连接数为 100 个。
- SetConnMaxLifetime 设置一个连接空闲后在多长时间内可复用,上面配置文件里设置的是300000000000, 因为Go的time.Duration底层类型是int64, 一秒是1000000000,这个大家可设置一个适当的时间,一般5~15分钟,不要太长。
Open 方法的第二个参数我们传递了一个 &gorm.Config{} ,里面没有设置任何配置选项
db, err := gorm.Open(mysql.Open(option.DSN), &gorm.Config{})
我们暂时还用不到它,下一节当我们需要把GORM日志整合到应用日志时才会用到它。
读写分离和多数据源配置
读写分离
首先GORM V2 版本支持一个自动按照执行的语句进行读写分离连接切换的功能 DBResolver,但是感觉用起来还是比较麻烦。
这个大家可以自己研究一下,这里为介绍一个在GORM V1时就一直用的土办法,这种方法虽然不支持自动切换,但贵在简单,在写Dao方法时根据逻辑类型选择对应的DB连接即可。
我们在在 dal/dao 的 gorminit.go 文件开头定义好保存主库和读库实例的变量
var _DbMaster *gorm.DB
var _DbSlave *gorm.DB
// DB 返回只读实例
func DB() *gorm.DB {
return _DbSlave
}
// DBMaster 返回主库实例
func DBMaster() *gorm.DB {
return _DbMaster
}
为每个变量提供了Getter方法,这样使用起来代码更简洁一些。初始化主库和从库的DB连接时,在init方法中使用上面介绍过的initDB方法,用主从库各自的配置进行初始化。
在写DAO方法时根据逻辑类型选择对应的DB连接使用。
多数据源配置
有的时候你的项目里的数据可能来自不同的数据库,那么现在项目的配置和初始化方法还不支持多数据源。
一开始做项目的时候我确实没有考虑到这个问题,工作中大部分DB用的也是MySQL,所以这里设计的不够灵活,好在咱们读者中已经有人开始在项目中使用起来了,并且还做了多数据源的扩展。