前言

平时写项目都是习惯于将什么Mysql,Redis,Kafka等这些需要配置的配置信息单独用一个conf文件来进行存放,以便管理


一、ini包

首先一个方法是比较轻量级的方法,就是ini包里的方法,很简单便捷


1、下载

go get gopkg.in/ini.v1

2、使用方法

一般将配置信息使用
这个ini文件进行存储
格式如下

[database]
Db = mysql
DbHost = 127.0.0.1
DbPort = 3306
DbUser = root
DbPassWord = ******
DbName = ****

[kafka]
address =127.0.0.1:9092
topic = web_log

[collect]
logfile_path =d:\logs\s4.log

使用这个包我们一般有两种方式


法一:简单方法

file, err := ini.Load("conf/config.ini")
if err != nil {
	fmt.Println("配置文件读取错误,请检查文件路径:", err)
}

读取到配置文件内容到file中

	DbHost = file.Section("database").Key("DbHost").String()
	DbPort = file.Section("database").Key("DbPort").String()
	DbUser = file.Section("database").Key("DbUser").String()
	DbPassWord = file.Section("database").Key("DbPassWord").String()
	DbName = file.Section("database").Key("DbName").String()
	fmt.Println(DbHost, DbPort, DbUser, DbPassWord, DbName)
// 127.0.0.1 3306 root 123456 ginblog

这样就可以拿到具体的key了

而一般来讲为了模块化都会将不同技术的配置信息封装到不同的函数里进行模块化管理
eg:

		func LoadData(file *ini.File) {...}
		func LoadKafka(file *ini.File) {...}
		func LoadRedis(file *ini.File) {...}

法二:结构体反射

把配置文件里的信息提前使用结构体封装然后进行反射

type Config struct {
	KafkaConfig `ini:"kafka"`
	Collect     `ini:"collect"`
	Etcd        `ini:"etcd"`
}

type KafkaConfig struct {
	Address string `ini:"address"`
	Topic   string `ini:"topic"`
}

type Collect struct {
	LogFilePath string `ini:"logfile_path"`
}

type Etcd struct {
	Address     string `ini:"address"`
	Collect_key string `ini:"collect_key"`
}

然后使用结构体的tag进行反射读取配置信息

var configObj = new(Config)
err := ini.MapTo(configObj, "./conf/Config.ini")
if err != nil {
	logrus.Error("config failed err:", err)
	return
}

这样操作一番所有的配置信息都拿到了在configObj中,比法一更加的一步到位


二、viper配置管理

viper相较于法一的包就比较重量级了,比较的完善,现如今也是go比较流行的完整配置解决方案


1、下载

go get github.com/spf13/viper

2、viper的特点

viper的特性如下

设置默认值
从JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件读取配置信息
实时监控和重新读取配置文件(可选)
从环境变量中读取
从远程配置系统(etcd或Consul)读取并监控配置变化
从命令行参数读取配置
从buffer读取配置 显式配置值

而本文章主要讲解viper从配置文件读取信息并实时监控配置文件进行热加载
若对其他内容有兴趣可以看看李文周老师博客进行了解

3、使用方法

跟ini一样一般创建一个conf文件存储配置信息,本次例子用yaml文件做例子

mysql:
  host: 127.0.0.1
  port: 3306
  user: "root"
  password: "****"
  dbname: "****"
  max_open_conns: 20
  max_idle_conns: 20
redis:
  host: 127.0.0.1
  port: 6379
  password: ""
  db: 0
  pool_size: 100

读取

首先一样的也是建结构体进行反射

type AppConfig struct {
	*MySQLConfig `mapstructure:"mysql"`
	*RedisConfig `mapstructure:"redis"`
}
type MySQLConfig struct {
	Host         string `mapstructure:"host"`
	User         string `mapstructure:"user"`
	Password     string `mapstructure:"password"`
	DB           string `mapstructure:"dbname"`
	Port         int    `mapstructure:"port"`
	MaxOpenConns int    `mapstructure:"max_open_conns"`
	MaxIdleConns int    `mapstructure:"max_idle_conns"`
}

type RedisConfig struct {
	Host         string `mapstructure:"host"`
	Password     string `mapstructure:"password"`
	Port         int    `mapstructure:"port"`
	DB           int    `mapstructure:"db"`
	PoolSize     int    `mapstructure:"pool_size"`
	MinIdleConns int    `mapstructure:"min_idle_conns"`
}

然后就是使用viper进行读取

	viper.SetConfigFile("config配置文件绝对路径")
	err = viper.ReadInConfig() // 读取配置信息
	if err != nil {
		// 读取配置信息失败
		fmt.Printf("viper Read Config failed, err:%v\n", err)
		return
	}

	// 把读取到的配置信息反序列化到 Conf 变量中
	if err := viper.Unmarshal(Conf); err != nil {
		fmt.Printf("viper Unmarshal failed, err:%v\n", err)
	}

	viper.WatchConfig()  // 对配置文件进行监视,若有改变就重新反序列到Conf中
	viper.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("配置文件修改了...")
		if err := viper.Unmarshal(Conf); err != nil {
			fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
		}
	})
	return
}

这就是使用viper对配置文件进行管理的方法

总结

不管是ini还是viper,可以看到都是非常方便的,但是viper的功能更加完善,更适用于企业级开发吧,ini就适合小型项目的使用就我个人感觉