目录

Golang viper 配置文件

viper 简介

Viper 是 Go 应用程序的完整配置解决方案,包括 12-Factor 应用程序。它旨在在应用程序中工作,并且可以处理所有类型的配置需求和格式。它支持:

  • 设置默认值
  • 从 JSON、TOML、YAML、HCL、envfile 和 Java 属性配置文件中读取
  • 实时观看和重新读取配置文件(可选)
  • 从环境变量中读取
  • 从远程配置系统(etcd 或 Consul)读取,并观察变化
  • 从命令行标志读取
  • 从缓冲区读取
  • 设置显式值

读取配置文件

app.yaml

1
2
3
4
5
6
server:
  host: 0.0.0.0
  port: 9090
log:
  level: debug
  format: json

main.go 创建配置文件结构体

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var cfg Cfg

type Cfg struct {
  Server Server `yaml:"server"`
  Log    Log    `yaml:"log"`
}
type Server struct {
  Host string `yaml:"host"`
  Port int    `yaml:"port"`
}

type Log struct {
  Level  string `yaml:"level"`
  Format string `yaml:"format"`
}

使用 viper 读取配置文件并解析到结构体

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func initConfig() {
  viper.AddConfigPath("./")
  viper.SetConfigName("apps")
  viper.SetConfigType("yaml")
  if err := viper.ReadInConfig(); err != nil {
    log.Fatalf("read config file failed, %v", err)
  }
  if err := viper.Unmarshal(&cfg); err != nil {
    log.Printf("unmarshal config file failed, %v", err)
  }
  log.Printf("%#v", cfg)
}

设置日志相关参数

 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
func initLog() {
  switch strings.ToLower(cfg.Log.Level) {
  case "panic":
    logrus.SetLevel(logrus.PanicLevel)
  case "fatal":
    logrus.SetLevel(logrus.FatalLevel)
  case "error":
    logrus.SetLevel(logrus.ErrorLevel)
  case "warn", "warning":
    logrus.SetLevel(logrus.WarnLevel)
  case "info":
    logrus.SetLevel(logrus.InfoLevel)
  case "debug":
    logrus.SetLevel(logrus.DebugLevel)
  case "trace":
    logrus.SetLevel(logrus.TraceLevel)
  default:
    logrus.SetLevel(logrus.InfoLevel)
  }
  switch strings.ToLower(cfg.Log.Format) {
  case "json":
    logrus.SetFormatter(&logrus.JSONFormatter{})
  case "text":
    logrus.SetFormatter(&logrus.TextFormatter{})
  default:
    logrus.SetFormatter(&logrus.TextFormatter{})
  }
}

main 函数

1
2
3
4
5
6
7
8
func main() {
  r := gin.Default()
  logrus.Debug("i'm a debug log")
  logrus.Info("i'm a info log")
  logrus.Warn("i'm a warn log")
  logrus.Error("i'm a error log")
  r.Run(cfg.Server.Host + ":" + strconv.Itoa(cfg.Server.Port))
}

go run main.go 输出结果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
main.Cfg{Server:main.Server{Host:"0.0.0.0", Port:9090}, Log:main.Log{Level:"debug", Format:"json"}}
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

{"level":"debug","msg":"i'm a debug log","time":"2021-06-30T10:12:16+08:00"}
{"level":"info","msg":"i'm a info log","time":"2021-06-30T10:12:16+08:00"}
{"level":"warning","msg":"i'm a warn log","time":"2021-06-30T10:12:16+08:00"}
{"level":"error","msg":"i'm a error log","time":"2021-06-30T10:12:16+08:00"}
[GIN-debug] Listening and serving HTTP on 0.0.0.0:9090

可以看到已经从配置文件读取到配置了。

从环境变量读取配置

1.修改 initConfig 函数,开启自动注入环境变量功能

在读取配置文件之前使用 AutomaticEnv,并使用 SetEnvKeyReplacer 将".“替换为”_"

1
2
3
4
5
viper.SetConfigType("yaml")
viper.AutomaticEnv()
replacer := strings.NewReplacer(".", "_")
viper.SetEnvKeyReplacer(replacer)
if err := viper.ReadInConfig(); err != nil { }

环境变量的格式为:SERVER_PORT

2.运行测试

SERVER_PORT=10086 go run main.go

修改日志相关变量

LOG_LEVEL=info LOG_FORMAT=text go run main.go

参考

https://huangzhongde.cn/post/Golang/%E4%BD%BF%E7%94%A8viper%E8%AF%BB%E5%8F%96%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%B9%B6%E5%85%81%E8%AE%B8%E4%BD%BF%E7%94%A8%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F/