Skip to main content

init config with viper

· 3 min read

简介

viper是go语言配置文件的一个管理库,github star 23.2K

viper有以下特性:

  • 设置默认值
  • 从json, toml,yaml,envfile 和 java properties格式的配置文件读取配置信息
  • 实时监控和重新读区配置文件
  • 从远程配置系统(etcd或consul)读取并监控配置变化
  • 从命令行参数读取配置
  • 从buffer读区配置
  • 设置显式值

get started

下面来看看viper的简单用法, 以config.yml为例

#install
go get github.com/spf13/viper

目录结构:

package main

import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"log"
"os"
"path"
)

type Config struct {
Use string `mapstructure:"use"`
Cfg []Server `mapstructure:"cfg"`
}

type Server struct {
Name string `mapstructure:"name"`
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Likes []string `mapstructure:"likes"`
}

func main() {
pth := path.Join(os.Getenv("GOPATH"), "src/github.com/scott-x/test")

// name of config file (without extension)
viper.SetConfigName("config")
// REQUIRED if the config file does not have the extension in the name
viper.SetConfigType("yaml")
// optionally look for config in the working directory
viper.AddConfigPath(".")
// path to look for the config file in
viper.AddConfigPath(pth)

err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
panic(fmt.Errorf("fatal error config file: %w", err))
}

var config Config
if err = viper.Unmarshal(&config); err != nil {
panic("Unmarshal failed:" + err.Error())
}
log.Println(config)

go func() {
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
viper.WatchConfig()
}()
}

运行:

在不修改源码的情况下实现线上线下环境分离

思路:

  • 1,线下创建一个环境变量,如果能够读到就为debug模式,否则为生产模式
  • 2,利用flag 命令行指定环境 eg: xx -env debug

下面展示环境变量的用法,eg:

export TEST_ENV=1

代码结构:

package main

import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"log"
"os"
"path"
)

type Config struct {
Mysql `mapstructure:"mysql"`
}

type Mysql struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"prot"`
Username string `mapstructure:"username"`
}

func main() {
pth := path.Join(os.Getenv("GOPATH"), "src/github.com/scott-x/test/env")
var configFileName, env string
if myenv := os.Getenv("TEST_ENV"); len(myenv) > 0 {
env = "debug"
} else {
env = "pro"
}
configFileName = fmt.Sprintf("config-%s.yml", env)
log.Println("configFileName:", configFileName)

// name of config file (without extension)
viper.SetConfigName(configFileName)
// REQUIRED if the config file does not have the extension in the name
viper.SetConfigType("yaml")
// optionally look for config in the working directory
viper.AddConfigPath(".")
// path to look for the config file in
viper.AddConfigPath(pth)

err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
panic(fmt.Errorf("fatal error config file: %w", err))
}

var config Config
if err = viper.Unmarshal(&config); err != nil {
panic("Unmarshal failed:" + err.Error())
}
log.Println(config)

go func() {
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
viper.WatchConfig()
}()
}

不设置环境变量运行:

设置环境变量后运行: