自定义配置
项目中配置文件是必不可少的,本文主要讲解了如何使用dubbo-go
现有的库加载并初始化自定义的配置文件
主要以配置 MySQL和 Redis 为例,完整代码见02-custom-config-file
编写配置文件
配置文件的格式有很多种,本文选择 yaml
格式,其是JSON的超集,不仅提供了更加简洁易懂的语法,还具有极强的可读性并提供了更多功能,例如引用、类型的自动检测以及支持对齐的多行值。
接下来开始编写配置文件,在 conf
目录下新建 data.yml
文件,并填入以下内容:
mysql:
dsn: "root:123456@tcp(127.0.0.1:3306)/study?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8mb4"
log_mode: false
max_open_conns: 10
max_idle_conns: 10
redis:
host: "127.0.0.1"
port: 6379
password: ""
db: 0 # use default DB
pool_size: 100
min_idle_conns: 5
定义结构体
在读取配置时,可以直接读取配置文件中的值,也可以将其映射到结构体中,方便我们统一管理及使用。
我们主要定义了三个结构体:
AppConfig
: 应用配置,集中管理所有配置MySQLConfig
:MySQL配置RedisConfig
:Redis配置
具体定义如下:
// AppConfig my app config
type AppConfig struct {
MySQLConfig `yaml:"mysql"`
RedisConfig `yaml:"redis"`
}
// MySQLConfig mysql config
type MySQLConfig struct {
DSN string `yaml:"dsn"` // write data source name.
LogMode bool `yaml:"log_mode"` // whether to open the log
MaxOpenConns int `yaml:"max_open_conns"` // max open conns
MaxIdleConns int `yaml:"max_idle_conns"` // max idle conns
}
// RedisConfig redis config
type RedisConfig struct {
Host string `yaml:"host"`
Password string `yaml:"password"`
Port int `yaml:"port"`
DB int `yaml:"db"`
PoolSize int `yaml:"pool_size"`
MinIdleConns int `yaml:"min_idle_conns"`
}
读取配置并序列化到Go结构体中
我们使用 dubbo-go
封装好的 yaml
库来解析配置文件,并将其内容序列化到上述定义的结构体中:
package conf
import (
"flag"
"github.com/apache/dubbo-go/common/yaml"
)
const defaultConfigFile = "../conf/data.yml"
func Init() (config *AppConfig, err error) {
var (
b []byte
configFile string
)
// 1.Specify the configuration file using command line parameters
flag.StringVar(&configFile, "dataConf", "../conf/data.yml", "choose conf file.")
flag.Parse()
if configFile == "" {
configFile = defaultConfigFile
}
// 2.Load yml config
if b, err = yaml.LoadYMLConfig(configFile); err != nil {
return
}
// 3.Serialize the contents of the configuration file to struct
config = new(AppConfig)
if err = yaml.UnmarshalYML(b, config); err != nil {
return
}
return
}
MySQL 初识化
我们使用 gorm 来操作MySQL,以下代码是初始化 gorm.DB
var (
sqlDB *sql.DB
)
// InitMySQL init gorm.DB
func InitMySQL(cfg *conf.AppConfig) (db *gorm.DB, err error) {
mysqlConf := mysql.Config{
DSN: cfg.DSN, // DSN data source name
DefaultStringSize: 256, // string 类型字段的默认长度
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
}
gormConfig := isLogOn(cfg.LogMode)
if db, err = gorm.Open(mysql.New(mysqlConf), gormConfig); err != nil {
logger.Error("database:opens database failed", err)
return
}
if sqlDB, err = db.DB(); err != nil {
logger.Error("database:get DB() failed", err)
return
}
// GORM 使用 database/sql 维护连接池
sqlDB.SetMaxIdleConns(cfg.MaxIdleConns) // 设置空闲连接池中连接的最大数量
sqlDB.SetMaxOpenConns(cfg.MaxOpenConns) // 设置打开数据库连接的最大数量
return
}
// isLogOn gorm 日志配置,mod为true,表示开启日志
func isLogOn(mod bool) (c *gorm.Config) {
if mod {
c = &gorm.Config{
Logger: gormLog.Default.LogMode(gormLog.Info),
DisableForeignKeyConstraintWhenMigrating: true,
NamingStrategy: schema.NamingStrategy{
// Whether the data table name is in plural form,default:false for plural table's name
SingularTable: true,
},
}
} else {
c = &gorm.Config{
Logger: gormLog.Default.LogMode(gormLog.Silent),
DisableForeignKeyConstraintWhenMigrating: true,
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
}
}
return
}
Redis 初识化
我们使用 go-redis 来操作Redis,以下代码是初始化 redis.Client
:
var rdb *redis.Client
// Init init redis client
func InitRedis(cfg *conf.AppConfig) (*redis.Client, error) {
rdb = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", cfg.RedisConfig.Host, cfg.RedisConfig.Port),
Password: cfg.Password, // no password set
DB: cfg.DB, // use default db
PoolSize: cfg.PoolSize, // redis connection pool size
MinIdleConns: cfg.MinIdleConns, // Set the minimum number of connections in the idle connection pool
})
if _, err := rdb.Ping().Result(); err != nil {
logger.Error("redis ping failed", err)
return nil, err
}
return rdb, nil
}
// Close close redis client
func Close() {
_ = rdb.Close()
}
总结
main.go
中调用了上述定义的方法以作验证,具体逻辑很简单。
dubbo-go
启动时需要配置 server.yml 和 log.yml,这两个配置我们只需要配置即可,不需要我们手动读取并初始化。
项目开发中,除了MySQL\Redis,可能还会使用其他中间件,此时也可以仿照上述方式来读取并初始化自定义配置。