Go一站式配置管理工具Viper的使用教程

 更新时间:2023年08月29日 09:44:17   作者:rickiyang  
Viper是一个方便Go语言应用程序处理配置信息的库,它可以处理多种格式的配置,这篇文章主要为大家介绍了它的具体使用教程,需要的可以参考下

什么是Viper

Viper是一个方便Go语言应用程序处理配置信息的库。它可以处理多种格式的配置。它支持的特性:

  • 设置默认值
  • 从JSON、TOML、YAML、HCL和Java properties文件中读取配置数据
  • 可以监视配置文件的变动、重新读取配置文件
  • 从环境变量中读取配置数据
  • 从远端配置系统中读取数据,并监视它们(比如etcd、Consul)
  • 从命令参数中读物配置
  • 从buffer中读取
  • 调用函数设置配置信息

为什么要使用Viper

在构建现代应用程序时,您不必担心配置文件格式; 你可以专注于构建出色的软件。
Viper 可以做如下工作:

  • 加载并解析JSON、TOML、YAML、HCL 或 Java properties 格式的配置文件
  • 可以为各种配置项设置默认值
  • 可以在命令行中指定配置项来覆盖配置值
  • 提供了别名系统,可以不破坏现有代码来实现参数重命名
  • 可以很容易地分辨出用户提供的命令行参数或配置文件与默认相同的区别

Viper读取配置信息的优先级顺序,从高到低,如下:

  • 显式调用Set函数
  • 命令行参数
  • 环境变量
  • 配置文件
  • key/value 存储系统
  • 默认值

Viper 的配置项的key不区分大小写。

项目地址:https://github.com/spf13/viper

使用

设置默认值

默认值不是必须的,如果配置文件、环境变量、远程配置系统、命令行参数、Set函数都没有指定时,默认值将起作用。

viper.SetDefault("name", "xiaoming")
viper.SetDefault("age", "12")
viper.SetDefault("notifyList", []string{"xiaohong","xiaoli","xiaowang"})

读取配置文件

Viper支持JSON、TOML、YAML、HCL和Java properties文件。

Viper可以搜索多个路径,但目前单个Viper实例仅支持单个配置文件

Viper默认不搜索任何路径。

以下是如何使用Viper搜索和读取配置文件的示例。

路径不是必需的,但最好至少应提供一个路径,以便找到一个配置文件。

viper.SetConfigName("dbConfig") //  设置配置文件名 (不带后缀)
viper.AddConfigPath("/workspace/appName/")   // 第一个搜索路径
viper.AddConfigPath("/workspace/appName1")  // 可以多次调用添加路径
viper.AddConfigPath(".")               // 比如添加当前目录
err := viper.ReadInConfig() // 搜索路径,并读取配置数据
if err != nil {
  panic(fmt.Errorf("Fatal error config file: %s \n", err))
}

监视配置文件,重新读取配置数据

Viper支持让你的应用程序在运行时拥有读取配置文件的能力。

只需要调用viper实例的WatchConfig函数,你也可以指定一个回调函数来获得变动的通知。

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

从 io.Reader 中读取配置

Viper预先定义了许多配置源,例如文件、环境变量、命令行参数和远程K / V存储系统。也可以实现自己的配置源,并提供给viper。

现在有如下yaml文件:

userName: "xiaoming"
address: "广州市XXX"
sex: 1
company:
  name: "xxx"
  employeeId: 1000
  department:
    - "技术部"

读取文件的代码如下:

package main
import (
	"fmt"
	"github.com/spf13/viper"
)
type UserInfo struct {
	UserName string
	Address string
	Sex byte
	Company Company
}
type Company struct {
	Name string
	EmployeeId int
	Department []interface{}
}
func main() {
	//读取yaml文件
	v := viper.New()
	//设置读取的配置文件名
	v.SetConfigName("userInfo")
	//windows环境下为%GOPATH,linux环境下为$GOPATH
	v.AddConfigPath("/Users/yangyue/workspace/go/src/webDemo/")
	//设置配置文件类型
	v.SetConfigType("yaml")
	if err := v.ReadInConfig();err != nil {
		fmt.Printf("err:%s\n",err)
	}
	fmt.Printf("userName:%s sex:%s company.name:%s \n", v.Get("userName"), v.Get("sex"), v.Get("company.name"))
  //也可以直接反序列化为Struct
	var userInfo UserInfo
	if err := v.Unmarshal(&userInfo) ; err != nil{
		fmt.Printf("err:%s",err)
	}
	fmt.Println(userInfo)
}

上面的代码使用两种方式获取配置文件:第一种直接解析为key,value;第二种你可以手动的反序列化为Struct。

从命令行参数中读取

package main
import (
	"fmt"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)
func main() {
	pflag.String("ip", "127.0.0.1", "Server running address")
	pflag.Int64("port", 8080, "Server running port")
	pflag.Parse()
	viper.BindPFlags(pflag.CommandLine)
	fmt.Printf("ip :%s , port:%s", viper.GetString("ip"), viper.GetString("port"))
}

命令行执行上面程序:

# go run test.go --ip=192.168.7.3 --port=3306

可以看到输出的是我们自定义的参数。

读取环境变量参数

一般获取环境变量使用os包,比如:

getenv := os.Getenv("JAVA_HOME")
fmt.Print(getenv)

Viper也提供了一种方式:

//表示 先预加载匹配的环境变量
viper.AutomaticEnv()
//读取已经加载到default中的环境变量
if env := viper.Get("JAVA_HOME"); env == nil {
    println("error!")
} else {
    fmt.Printf("%#v\n", env)
}

由获取环境变量我们是不是可以想到多环境参数配置呢?针对线上环境,开发环境分别加载不同yml中的参数。

func initConfig() (err error) {
	env := os.Getenv("GO_ENV")
	viper.SetConfigName(env)
	viper.AddConfigPath("./configs")
	viper.SetConfigType("yml")
	err = viper.ReadInConfig()
	return
}

因为无论是线上环境还是测试环境,肯定有一些参数是公共不变的,那么这一部分参数是否可以抽出来作为一个单独的配置文件呢。所以这样配置文件可以分为两个部分:

"github.com/gobuffalo/packr"
func initConfig() (err error) {
	box := packr.NewBox("./configs")
	configType := "yml"
	defaultConfig, _ := box.Find("default.yml")
	v := viper.New()
	v.SetConfigType(configType)
	err = v.ReadConfig(bytes.NewReader(defaultConfig))
	if err != nil {
		return
	}
	configs := v.AllSettings()
	// 将default中的配置全部以默认配置写入
	for k, v := range configs {
		viper.SetDefault(k, v)
	}
	env := os.Getenv("GO_ENV")
	// 根据配置的env读取相应的配置信息
	if env != "" {
		envConfig, _ := box.Find(env + ".yml")
		viper.SetConfigType(configType)
		err = viper.ReadConfig(bytes.NewReader(envConfig))
		if err != nil {
			return
		}
	}
	return
}

首先读取default.yml中的参数,将其写入default中。然后再根据环境变量读取不同环境中的参数。

这里使用了packr包,packr包的作用在于将静态资源打包至应用程序中。

以上就是Go一站式配置管理工具Viper的使用教程的详细内容,更多关于Go Viper的资料请关注脚本之家其它相关文章!

相关文章

  • golang MarshalJson的实现

    golang MarshalJson的实现

    本文主要介绍了golang MarshalJson的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-03-03
  • Golang栈结构和后缀表达式实现计算器示例

    Golang栈结构和后缀表达式实现计算器示例

    这篇文章主要为大家介绍了Golang栈结构和后缀表达式实现计算器示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • Golang Slice和map的坑

    Golang Slice和map的坑

    Golang中的Slice和Map在内存空间上,有一些不同,本文主要介绍了Golang Slice和map的坑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-04-04
  • Go+Kafka实现延迟消息的实现示例

    Go+Kafka实现延迟消息的实现示例

    本文主要介绍了Go+Kafka实现延迟消息的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Go语言TCP从原理到代码实现详解

    Go语言TCP从原理到代码实现详解

    这篇文章主要为大家介绍了Go语言TCP从原理到代码实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • goland 实现websocket server的示例代码

    goland 实现websocket server的示例代码

    本文主要介绍了goland 实现websocket server的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • golang切片扩容规则实现

    golang切片扩容规则实现

    这篇文章主要介绍了golang切片扩容规则实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • GO语言并发编程之互斥锁、读写锁详解

    GO语言并发编程之互斥锁、读写锁详解

    这篇文章主要介绍了GO语言并发编程之互斥锁、读写锁详解,本文是GO并发编程实战一书的样章,详细讲解了互斥锁、读写锁,然后给出了一个完整示例,需要的朋友可以参考下
    2014-11-11
  • Go语言基础模板设计模式示例详解

    Go语言基础模板设计模式示例详解

    这篇文章主要为大家介绍了Go语言基础设计模式之模板模式的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-11-11
  • Golang中使用不定数量空格分割字符串的方法

    Golang中使用不定数量空格分割字符串的方法

    有这样一个使用空格分割字符串的场景,字符串中被分割的子串之间的空格数量不确定,有一个两个或者多个空格,这种场景下,使用最容易想到的strings.Split函数就做不到了,本文接下来就介绍几种行之有效的方法,需要的朋友可以参考下
    2023-07-07

最新评论