Bootstrap

golang入门笔记——viper

Viper是golang的一个管理配置文件的工具,它支持JSON、TOML、YAML、HCL、envfile、Java properties。它支持以下特性:

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

Viper优先级:

显示调用 Set设置值
命令行参数 (flag)
环境变量
配置文件
key/value存储
默认值

注意:

viper是大小写敏感的

Viper库的安装:

 go get github.com/spf13/viper

viper的简单使用:

func ReadFromConfig() {
	config := viper.New()            //创建一个viper文件
	config.AddConfigPath("./config") //配置文件所在目录
	//config.SetConfigFile("./config.yaml") // 指定配置文件路径
	//config.AddConfigPath("$HOME/.appname")  // 多次调用以添加多个搜索路径
	config.SetConfigName("account")  //文件名
	config.SetConfigType("json")     //文件类型,配置文件的后缀
	if err := config.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			panic("找不到配置文件")
		} else {
			panic(err)
		}
	}
	//读取配置
	user1 := config.GetString("section1.user")
	user2 := config.GetString("section2.user")
	height := config.GetInt32("section1.body.height")
	weight := config.GetInt32("section1.body.weight")
	fmt.Println(user1, user2, height, weight)
}

viper的其它用法

//设置配置的默认值
config.SetDefault("ContentKey", "content")

//写入配置文件
WriteConfig - 将当前的viper配置写入预定义的路径并覆盖(如果存在的话)。如果没有预定义的路径,则报错。
SafeWriteConfig - 将当前的viper配置写入预定义的路径。如果没有预定义的路径,则报错。如果存在内容,将不会覆盖当前的配置文件。
WriteConfigAs - 将当前的viper配置写入给定的文件路径。将覆盖给定的文件(如果它存在的话)。
SafeWriteConfigAs - 将当前的viper配置写入给定的文件路径。如果存在内容,不会覆盖给定的文件(如果它存在的话)

监控并重新读取配置

Viper支持在运行时实时读取配置文件的功能。

需要重新启动服务器以使配置生效的日子已经一去不复返了,viper驱动的应用程序可以在运行时读取配置文件的更新,而不会错过任何消息。

只需告诉viper实例watchConfig。可选地,你可以为Viper提供一个回调函数,以便在每次发生更改时运行。

	config.SetDefault("ContentDir", "content")
	config.SetDefault("LayoutDir", "layouts")
	config.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
	config.WatchConfig()
	config.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("Config file changed:", in.Name)
		config.ReadInConfig()
		get := config.Get("ContentDir")
		fmt.Println("contentdir:", get.(string))
	})

注册和使用别名

	config.RegisterAlias("contentdir", "dir") //创建一个新字段dir,当修改contentdir时,dir也会改变,修改dir时,contentdir也会改变
	config.Set("contentdir", "/test")         //覆盖contentdir,SetDefault是指当contentdir没值时才会set

json配置的获取

{
  "datastore.metric.host": "0.0.0.0",
  "host": {
    "address": "localhost",
    "port": 5799
  },
  "datastore": {
    "metric": {
      "host": "127.0.0.1",
      "port": 3099
    },
    "warehouse": {
      "host": "198.0.0.1",
      "port": 2112
    }
  }
}
	config := viper.New()
	config.AddConfigPath("./")
	config.SetConfigName("account")
	config.SetConfigType("json")
	err := config.ReadInConfig()
	if _, ok := err.(viper.ConfigFileNotFoundError); ok {
		panic("config file not found")
	} else if err != nil {
		panic(err)
	}
	fmt.Println(config.GetString("host.address")) //通过.来获取json中的嵌套字段

使用环境变量:

SetEnvPrefix:用于不知道环境变量名时,viper自动查找的时候加的前缀名,BindEnv和AutomaticEnv都将使用这个前缀

config.SetEnvPrefix("spf") //自动将spf转为大写

BindEnv使用一个或者两个参数:第一个参数是键名称,第二个参数是环境变量名。环境变量的名称区分大小写。如果没有指定环境变量名,会把“前缀+“_”+键名全部大写”。作为默认的环境变量名。如果包含两个参数时,它不会自动加前缀

config.BindEnv("id") //一个参数时,使用SPF_ID作为默认的环境变量值
config.BindEnv("id","ID") //将ID绑定到id变量上

id:=config.Get("id")

获取子树

contentdir: /dir
dir: /dir
layoutdir: layouts
mysql:
    dbname: sql_demo
    host: 127.0.0.1
    port: 13306
port: 8081
taxonomies:
    category: categories
    tag:
        test: 1
        test2: 2
	subv := config.Sub("taxonomies.tag") //获取的是tag下的所有内容
	fmt.Println(subv.GetInt("test"))

从json对象直接Unmarshal出值

type Config struct {
	Port    int    `json:"port"`
	Version string `json:"version"`
}

var Conf = new(Config)

func ReadFromConfig() {
	config := viper.New()
	config.AddConfigPath("./")
	config.SetConfigName("account")
	config.SetConfigType("json")

	err := config.ReadInConfig()
	if _, ok := err.(viper.ConfigFileNotFoundError); ok {
		panic("config file not found")
	} else if err != nil {
		panic(err)
	}

	if err := config.Unmarshal(&Conf); err != nil {
		panic(err)
	}
	fmt.Println(Conf.Port, Conf.Version)
}
;