跳过正文
  1. 文章/
  2. GoLang/
  3. 常用包/
  4. 第三方包/

2、viper

·743 字·2 分钟· loading · loading · ·
GoLang 常用包 第三方包
GradyYoung
作者
GradyYoung
第三方包 - 点击查看当前系列文章
§ 2、viper 「 当前文章 」

viper 是一个配置解决方案,拥有丰富的特性:

  • 支持 JSONTOMLYAMLHCLenvfileJava properties 等多种格式的配置文件;
  • 可以设置监听配置文件的修改,修改时自动加载新的配置;
  • 从环境变量、命令行选项和io.Reader中读取配置;
  • 从远程配置系统中读取和监听修改,如 etcd/Consul
  • 代码逻辑中显示设置键值。

安装
#

go get -u github.com/spf13/viper

读取配置
#

使用默认实例读取配置文件

package main

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

func main() {
    viper.SetConfigName("config")  // 设置配置文件名,不包括扩展名
    viper.AddConfigPath("/etc/appname/") // 添加配置文件搜索路径
    viper.AddConfigPath("$HOME/.appname") // 可以添加多个搜索路径

    err := viper.ReadInConfig() // 读取配置文件
    if err != nil {
        panic(fmt.Errorf("Fatal error config file: %s \n", err))
    }

    // 使用 viper.Get 或其他类型特定方法获取配置
    fmt.Println(viper.GetString("somekey"))
}

也可以构造新的实例加载配置文件

package main

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

func main() {
	config := viper.New()
	config.SetConfigName("config")  // 设置配置文件名,不包括扩展名
	config.AddConfigPath("/etc/appname/") // 添加配置文件搜索路径
	config.AddConfigPath("$HOME/.appname") // 可以添加多个搜索路径

	err := config.ReadInConfig() // 读取配置文件
	if err != nil {
		panic(fmt.Errorf("Fatal error config file: %s \n", err))
	}

	// 使用 viper.Get 或其他类型特定方法获取配置
	fmt.Println(config.GetString("somekey"))
}

读取配置流
#

除了读取文件,Viper 还可以从任何实现了 io.Reader 接口的对象中读取配置。

viper.SetConfigType("yaml")
yamlExample := []byte(`
name: myapp
`)
viper.ReadConfig(bytes.NewBuffer(yamlExample))
fmt.Println(viper.Get("name"))

设置参数默认值
#

viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")

监听配置文件变化
#

Viper 支持监听配置文件的变化,并在文件更改时触发回调函数。

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

配置参数别名
#

viper.RegisterAlias("base", "alias")
viper.Set("base", true)
fmt.Println(viper.GetBool("base"))  // 输出: true
fmt.Println(viper.GetBool("alias")) // 输出: true

解序列化
#

可以选择将全部或特定值解序列化到一个结构体、映射等中。

有两种方法可以实现这一点:

  • Unmarshal(rawVal any) : error
  • UnmarshalKey(key string, rawVal any) : error
type config struct {
	Port int
	Name string
	PathMap string `mapstructure:"path_map"`
}

var C config

err := viper.Unmarshal(&C)
if err != nil {
	t.Fatalf("unable to decode into struct, %v", err)
}

写入配置文件
#

viper.WriteConfig() // 将当前配置写入“viper.AddConfigPath()”和“viper.SetConfigName”设置的预定义路径
viper.SafeWriteConfig()
viper.WriteConfigAs("/path/to/my/.config")
viper.SafeWriteConfigAs("/path/to/my/.config") // 因为该配置文件写入过,所以会报错
viper.SafeWriteConfigAs("/path/to/my/.other_config")

常见问题
#

配置属性含下划线无法读取
#

可以添加 Tag mapstructure 以读取带下划线的参数

type MySQL struct {
	DSN             string `yaml:"dsn" mapstructure:"dsn"`
	MaxIdleConns    int    `yaml:"max_idle_conns" mapstructure:"max_idle_conns"`
	MaxOpenConns    int    `yaml:"max_open_conns" mapstructure:"max_open_conns"`
	ConnMaxLifetime int    `yaml:"conn_max_lifetime" mapstructure:"conn_max_lifetime"`
}
第三方包 - 点击查看当前系列文章
§ 2、viper 「 当前文章 」