tonglin0325的个人主页

go学习笔记——配置

1.读取命令行参数#

1
2
3
4
func main() {
println("Hello ", os.Args[1])
}

配置arg

输出

1
2
Hello World

注意arg[0]是go程序的运行目录

2.使用flag加载环境变量#

golang内置的标准库flag,可以用来读取配置文件的路径

1
2
3
4
5
6
7
func main() {

var configFilePath = flag.String("conf", "./", "config file path") // flag也支持flag.Bool,flag.Int等用法
flag.Parse()
println(*configFilePath)
}

配置

输出

1
2
./configs

如果找不到-conf配置的话,才会输出 ./

3.使用toml或者multiconfig加载toml配置文件#

1.使用toml#

1
2
go get github.com/BurntSushi/toml@latest

参考:https://github.com/BurntSushi/toml

config.toml配置

1
2
3
4
5
6
Age = 25
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z

读取配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type Config struct {
Age int
Cats []string
Pi float64
Perfection []int
DOB time.Time // requires `import time`
}

func main() {

buf, err := os.ReadFile("./configs/config.toml")
tomlData := string(buf)
if err != nil {
panic(err)
}
var conf Config
if _, err := toml.Decode(tomlData, &conf); err != nil {
fmt.Println(err.Error())
}
fmt.Println(conf)

}

输出

1
2
{25 [Cauchy Plato] 3.14 [6 28 496 8128] 1987-07-05 05:45:00 +0000 UTC}

2.使用multiconfig#

1
2
go get github.com/koding/multiconfig

参考:https://github.com/koding/multiconfig

读取配置

1
2
3
4
5
6
7
8
9
10
11
12
func main() {

m := multiconfig.NewWithPath("./configs/config.toml") // supports TOML and JSON

// Get an empty struct for your configuration
conf := new(Config)

// Populated the serverConf struct
m.MustLoad(conf) // Check for error

fmt.Printf("%+v\n", conf)

输出

1
2
&{Age:25 Cats:[Cauchy Plato] Pi:3.14 Perfection:[6 28 496 8128] DOB:1987-07-05 05:45:00 +0000 UTC}

4.使用viper加载配置文件#

安装viper

1
2
go get github.com/spf13/viper

在config目录下添加viper.go文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package config

import "github.com/spf13/viper"

// 全局Viper变量
var Viper = viper.New()

func Load(configFilePath string) error {
Viper.SetConfigName("config") // config file name without file type
Viper.SetConfigType("yaml") // config file type
Viper.AddConfigPath(configFilePath) // config file path
return Viper.ReadInConfig()
}

配置文件

1
2
3
4
db:
mysql:
dsn: root:123456@tcp(127.0.0.1:55000)/test?charset=utf8mb4&parseTime=True

读取配置

1
2
3
4
5
6
7
8
9
10
11
12
func main() {

var configFilePath = flag.String("conf", "./", "config file path")
flag.Parse()

if err := config.Load(*configFilePath); err != nil {
panic(err)
}

println(config.Viper.GetString("db.mysql.dsn"))
}

 配置路径

参考:Go语言微服务框架 - 2.实现加载静态配置文件

viper还提供动态配置的功能,来实现热加载,可以使用go的协程来定时刷新配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package config

import (
"flag"
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)

// GlobalConfig 全局Viper变量
var GlobalConfig *viper.Viper

func init() {
initConfig()
go dynamicConfig()
}

func initConfig() {
var configFilePath = flag.String("conf", "./", "config file path")
flag.Parse()
GlobalConfig = viper.New()
GlobalConfig.AddConfigPath(*configFilePath) // config file path
GlobalConfig.SetConfigName("config") // config file name without file type
GlobalConfig.SetConfigType("yaml") // config file type
err := GlobalConfig.ReadInConfig() // 读取配置文件
if err != nil { // 可以按照这种写法,处理特定的找不到配置文件的情况
if v, ok := err.(viper.ConfigFileNotFoundError); ok {
fmt.Println(v)
} else {
panic(fmt.Errorf("read config err:%s\n", err))
}
}
}

// viper支持应用程序在运行中实时读取配置文件的能力。确保在调用 WatchConfig()之前添加所有的configPaths。
func dynamicConfig() {
GlobalConfig.WatchConfig()
GlobalConfig.OnConfigChange(func(event fsnotify.Event) {
fmt.Printf("发现配置信息发生变化: %s\n", event.String())
})
}

参考:go使用viper读取配置参数热加载