github.com/spf13/viper go viper包介绍
什么是Viper?
Viper是一个Go应用程序完整的配置文件解决方案,包括12-Factor应用程序。它被设计为:在应用程序中工作,可以处理所有类型的配置需求和格式。它支持:
- 设置默认值
- 从JSON,TOML,YAML,HCL和Java属性配置文件中读取
- 实时观看和重新读取配置文件(可选)
- 从环境变量中读取
- 从远程配置系统(etcd或Consul)读取,并观察变化
- 从命令行标志读取
- 从缓冲区读取
- 设置显式值
Viper可以被认为是所有应用程序配置需求的注册表。
为何选择Viper?
构建现代应用程序时,你不必担心配置文件格式,只需专注于构建给力的软件。Viper就是为此提供帮助的。
Viper为你做了以下事情:
- 查找、加载和解析以JSON,TOML,YAML,HCL或Java属性格式的配置文件。
- 提供一种机制,来为不同的配置选项设置默认值。
- 提供一种机制,来为通过命令行标志指定的选项设置覆盖值。
- 提供别名系统,轻松重命名参数,而不会破坏现有代码。
- 与默认值相同时,可以很容易地区分其来源于命令行或配置文件。
Viper使用以下优先顺序。每个项目优先于其下方的项目:
使用Viper设置默认值
- explicit call to Set
- flag
- env
- config
- key/value store
- default
viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
Viper读取配置文件
Viper需要最少的配置,因此它知道在哪里查找配置文件。Viper支持JSON,TOML,YAML,HCL和Java Properties文件。Viper可以搜索多个路径,但目前单个Viper实例仅支持单个配置文件。Viper不会默认使用任何配置搜索路径,而是将默认值决定应用于应用程序。
以下是如何使用Viper搜索和读取配置文件的示例。不需要任何特定路径,但应在预期配置文件的位置提供至少一个路径。
viper.SetConfigName("config") // name of config file (without extension)
viper.AddConfigPath("/etc/appname/") // path to look for the config file in
viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths
viper.AddConfigPath(".") // optionally look for config in the working directory
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: %s \n", err))
}
监听并重新读取配置文件
Viper支持在运行时让应用程序实时读取配置文件。
需要重新启动服务器以使配置生效的日子已经一去不复返了,viper驱动的应用程序可以在运行时读取配置文件的更新,而不会错过任何一个节拍。
只需告诉viper实例watchConfig即可。您可以选择为Viper提供每次发生更改时运行的功能。
确保在调用之前添加所有configPath WatchConfig()
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
从io.Reader读取配置
Viper预定义了许多配置源,例如文件,环境变量,标志和远程K / V存储,但您不受它们的约束。您还可以实现自己的必需配置源并将其提供给viper。
viper.SetConfigType("yaml") // 或viper.SetConfigType(“YAML”)
//任何需要将此配置放入程序的方法
var yamlExample = []byte(`
Hacker: true
name: steve
hobbies:
- skateboarding
- snowboarding
- go
clothing:
jacket: leather
trousers: denim
age: 35
eyes : brown
beard: true
`)
viper.ReadConfig(bytes.NewBuffer(yamlExample))
viper.Get("name")
Viper设置并覆盖配置值
viper.Set("Verbose", true)
viper.Set("LogFile", LogFile)
Viper注册和使用别名
别名允许多个键引用单个值
viper.RegisterAlias("loud", "Verbose")
viper.Set("verbose", true) // same result as next line
viper.Set("loud", true) // same result as prior line
viper.GetBool("loud") // true
viper.GetBool("verbose") // true
Viper使用环境变量
Viper完全支持环境变量。有四种方法可以帮助使用ENV:
AutomaticEnv()
BindEnv(string...) : error
SetEnvPrefix(string)
SetEnvKeyReplacer(string...) *strings.Replacer
BindEnv
需要一个或两个参数。第一个参数是键名,第二个是环境变量的名称。环境变量的名称区分大小写。如果未提供ENV变量名,则Viper将自动假设密钥名称与ENV变量名称匹配,但ENV变量为IN ALL CAPS。当您明确提供ENV变量名称时,它不会自动添加前缀。
使用ENV变量时要认识到的一件重要事情是每次访问时都会读取该值。Viper在BindEnv
调用时不会修复该值。
AutomaticEnv
尤其是当与结合了强大的帮手 SetEnvPrefix
。调用时,Viper将在任何viper.Get
请求发出时检查环境变量。它将适用以下规则。它将检查一个环境变量,其名称与大写的键匹配,并以EnvPrefix
前缀。
SetEnvKeyReplacer
允许您使用strings.Replacer
对象重写Env键到一定程度。如果要-
在Get()
调用中使用或使用某些内容 ,但希望环境变量使用_
分隔符,则此选项非常有用。可以在中找到使用它的示例viper_test.go
ENV实例
SetEnvPrefix("spf") //将自动大写
BindEnv("id")
os.Setenv("SPF_ID", "13") // 通常在应用以外完成
id := Get("id") // 13
使用flag
Viper能够绑定到flag。
就像BindEnv
,在调用绑定方法时,不会设置该值。这意味着您可以尽早绑定,甚至可以在init()
函数中绑定 。
对于单个标志,该BindPFlag()
方法提供此功能。
serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
您还可以绑定一组现有的pflags(pflag.FlagSet)
pflag.Int("flagname", 1234, "help message for flagname")
pflag.Parse()
viper.BindPFlags(pflag.CommandLine)
i := viper.GetInt("flagname")
在Viper中使用pflag并不排除使用 标准库中使用标志包的其他包。pflag包可以通过导入这些标志来处理为标志包定义的标志。这是通过调用名为AddGoFlagSet()的pflag包提供的便利函数来实现的。
package main
import (
"flag"
"github.com/spf13/pflag"
)
func main() {
// using standard library "flag" package
flag.Int("flagname", 1234, "help message for flagname")
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
viper.BindPFlags(pflag.CommandLine)
i := viper.GetInt("flagname") // retrieve value from viper
...
}
flag接口
如果您不使用,Viper提供两个Go接口来绑定其他标志系统Pflags
FlagValue
代表一个标志。这是一个关于如何实现此接口的非常简单的示例:
type myFlag struct {}
func (f myFlag)HasChanged()bool { return false }
func (f myFlag)Name()string { return “ my-flag-name ” }
func (f myFlag)ValueString()string { return “ my -flag-value “ }
func (f myFlag)ValueType()string { return “ string ” }
一旦你的flag实现了这个接口,你可以告诉Viper绑定它:
viper.BindFlagValue("my-flag-name", myFlag{})
远程key/value存储
要在Viper中启用远程支持,请对viper/remote
包进行空白导入:
import _ "github.com/spf13/viper/remote"
Viper将读取key/value存储(如etcd或Consul)中的路径检索的配置字符串(如JSON,TOML,YAML或HCL)。这些值优先于默认值,但会被从磁盘,标志或环境变量检索的配置值覆盖。
Viper使用crypt从K / V存储中检索配置,这意味着您可以存储加密的配置值,并在拥有正确的gpg密钥环时自动解密。加密是可选的。
您可以将远程配置与本地配置结合使用,也可以独立使用。
crypt
有一个命令行帮助程序,您可以使用它来将配置放入K / V存储区。crypt
在http://127.0.0.1:4001上默认为etcd 。
$ go get github.com/xordataexchange/crypt/bin/crypt
$ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
确认您的值已设置:
$ crypt get -plaintext /config/hugo.json
远程key/value存储示例 - 未加密
viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json")
viper.SetConfigType("json") //因为字节流中没有文件扩展名,支持的扩展名是“json”,“toml”,“yaml”,“yml”,“properties”,“props”,“prop”
err := viper.ReadRemoteConfig()
远程key/value存储示例 - 加密
viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg")
viper.SetConfigType("json") //因为字节流中没有文件扩展名,支持的扩展名是“json”,“toml”,“yaml”,“yml”,“properties”,“props”,“prop”
err := viper.ReadRemoteConfig()
监听etcd中的变化 - 未加密
//或者,您可以创建一个新的viper实例
var runtime_viper = viper.New()
runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml")
runtime_viper.SetConfigType("yaml")
// 第一次从远程配置中读取
err := runtime_viper.ReadRemoteConfig()
//解密配置
runtime_viper.Unmarshal(&runtime_conf)
// 打开一个goroutine来永远监听远程变化
go func(){
for {
time.Sleep(time.Second * 5) // 每次请求后延迟
err := runtime_viper.WatchRemoteConfig()
if err != nil {
log.Errorf("unable to read remote config: %v", err)
continue
}
//将新配置解组到我们的运行时配置结构中。您还可以使用通道
//实现信号以通知系统更改
runtime_viper.Unmarshal(&runtime_conf)
}
}()
Viper获取值
在Viper中,有几种方法可以根据值的类型获取值。存在以下功能和方法:
Get(key string) : interface{}
GetBool(key string) : bool
GetFloat64(key string) : float64
GetInt(key string) : int
GetString(key string) : string
GetStringMap(key string) : map[string]interface{}
GetStringMapString(key string) : map[string]string
GetStringSlice(key string) : []string
GetTime(key string) : time.Time
GetDuration(key string) : time.Duration
IsSet(key string) : bool
AllSettings() : map[string]interface{}
如果找不到,每个Get函数都将返回零值。IsSet()
方法检查给定密钥是否存在。
实例:
viper.GetString("logfile") // case-insensitive Setting & Getting
if viper.GetBool("verbose") {
fmt.Println("verbose enabled")
}
访问嵌套
访问器方法也接受深层嵌套键的格式化路径。例如,如果加载了以下JSON文件:
{
"host": {
"address": "localhost",
"port": 5799
},
"datastore": {
"metric": {
"host": "127.0.0.1",
"port": 3099
},
"warehouse": {
"host": "198.0.0.1",
"port": 2112
}
}
}
Viper可以通过传递.
分隔的键路径来访问嵌套字段:
GetString("datastore.metric.host") // (returns "127.0.0.1")
这符合上面建立的优先规则; 搜索路径将在剩余的配置注册表中级联,直到找到。
例如,给定此配置文件,都datastore.metric.host
和 datastore.metric.port
已经定义(并且可以被覆盖)。如果另外datastore.metric.protocol
在默认值中定义,Viper也会找到它。
但是,如果使用立即值datastore.metric
覆盖(通过标志,环境变量,Set()
方法,...),则所有子键 datastore.metric
变为未定义,它们将被更高优先级的配置级别“遮蔽”。
最后,如果存在与分隔的键路径匹配的键,则将返回其值。例如
{
"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
}
}
}
GetString("datastore.metric.host") // returns "0.0.0.0"
提取sub-tree
例如
app:
cache1:
max-items: 100
item-size: 64
cache2:
max-items: 200
item-size: 80
#执行后
subv := viper.Sub("app.cache1")
#subv为
max-items:100
item-size:64
假设
func NewCache(cfg *Viper) *Cache {...}
它根据格式化为的配置信息创建缓存subv
。现在可以轻松地分别创建这两个缓存:
cfg1 := viper.Sub("app.cache1")
cache1 := NewCache(cfg1)
cfg2 := viper.Sub("app.cache2")
cache2 := NewCache(cfg2)
遍历
您还可以选择Unmarshaling all或特定值到struct,map等。
有两种方法可以做到这一点:
Unmarshal(rawVal interface{}) : error
UnmarshalKey(key string, rawVal interface{}) : error
例如:
type config struct {
Port int
Name string
PathMap string `mapstructure:"path_map"`
}
var C config
err := Unmarshal(&C)
if err != nil {
t.Fatalf("unable to decode into struct, %v", err)
}
转为字符串
您可能需要将viper中保存的所有设置变为字符串,而不是将它们写入文件。您可以使用您喜欢的格式的marshaller和返回的配置AllSettings()
。
import (
yaml "gopkg.in/yaml.v2"
// ...
)
func yamlStringSettings() string {
c := viper.AllSettings()
bs, err := yaml.Marshal(c)
if err != nil {
t.Fatalf("unable to marshal config to YAML: %v", err)
}
return string(bs)
}
Viper or Vipers?
Viper随时可以使用。开始使用Viper无需配置或初始化。由于大多数应用程序都希望使用单个中央存储库进行配置,因此viper软件包提供了此功能。它类似于单身人士。
在上面的所有示例中,他们演示了使用viper的单例式方法。
使用多个Viper
您还可以创建许多不同的viper,以便在您的应用程序中使用。每个都有自己独特的配置和价值观。每个都可以从不同的配置文件,键值存储等中读取.viper包支持的所有功能都被镜像为viper上的方法。
例如
x := viper.New()
y := viper.New()
x.SetDefault("ContentDir", "content")
y.SetDefault("ContentDir", "foobar")
使用多viper时,用户可以跟踪不同的viper。
尊重别人劳动成果,原文地址:
https://blog.csdn.net/cs380637384/article/details/81217767
github.com/spf13/viper go viper包介绍相关推荐
- GitHub开源项目 - Jeecg-Boot开始开发平台介绍
GitHub开源项目 - Jeecg-Boot开始开发平台介绍 Jeecg-Boot 是一款基于SpringBoot+代码生成器的快速开发平台!采用前后端分离架构:SpringBoot,Mybatis ...
- go语言negroni包介绍
go语言negroni包介绍 前言 go语言很好地支持了网络编程,go 语言与web 框架相关的包有很多,本文主要介绍go语言的negroni包. 前置参考博客:HTTP 协议 与 golang we ...
- golang办公工作流workflow js-ojus/flow包介绍——系列一
golang语言的办公工作流的包介绍--系列一 golang办公工作流workflow利用js-ojus/flow做测试--系列二 golang办公流程引擎初体验js-ojus/flow--系列三 g ...
- 工具分享 | linemap-快速绘制山峦地图的R可视化包介绍
公众号后台回复"图书",了解更多号主新书内容 作者:宁海涛 来源:DataCharm 上一次介绍了Python绘制svg的优秀可视化库Pygal,今天我们介绍一下一个优秀的R地图可 ...
- 安装软件包的三种方法、rpm包介绍、rpm工具用法、yum工具用法、yum搭建本地仓库...
为什么80%的码农都做不了架构师?>>> 安装软件包的三种方法 rpm工具 yum工具 源码包 rpm rpm命令是RPM软件包的管理工具.rpm原本是Red Hat Linu ...
- 7.1 安装软件包的三种方法 7.2 rpm包介绍 7.3 rpm工具用法 7.4 yum工具用法 7.5 yum搭建本地仓库...
7.1 安装软件包的三种方法 7.2 rpm包介绍 7.3 rpm工具用法 7.4 yum工具用法 7.5 yum搭建本地仓库 三种方法 rpm工具----->类型windows下的exe程序 ...
- java中的jsonjar_java中使用json之相关jar包介绍
1.JSON产生的背景 Web开发过程中,在客户端与服务器之间离不开数据的交互,这就需要规定交互数据的相关格式,通常来说都是使用JSON来传递数据. 2.JSON对象以及JSON字符串 JSON对象和 ...
- Spring目录结构和基础JAR包介绍
目前 Spring 框架的最新版本是 5.1.8,本教程是基于 Spring 的稳定版本 3.2.13 进行讲解的.读者可以通过网址 http://repo.spring.io/simple/libs ...
- 《PHP挖宝》2—Symfony包介绍
<PHP挖宝>2-Symfony包介绍 文章目录 <PHP挖宝>2-Symfony包介绍 Hello World示例 Symfony使用的包 部分Symfony包介绍 < ...
最新文章
- 解决'ping' 不是内部或外部命令,也不是可运行的程序
- TensorFlow 笔记6--迁移学习
- 在iOS8 下用Swift 创建自定义的键盘
- Android studio导入support-v4.jar
- api自动化_如何在不增加人员的情况下自动化API安全程序
- 树莓派搭建私人服务器
- paip.注册java程序为LINUX系统服务的总结。
- 单片机矩阵键盘扫描程序c语言,51单片机矩阵键盘扫描程序(源代码)
- 【专项测试】京东“安全测试”
- 图像特征提取:Sobel边缘检测
- 常见计算机病毒有些什么症状,电脑中病毒的症状有哪些
- 编码至高法则-高内聚低耦合
- ros入门--中科院软件所ros学习笔记
- 计算机毕业设计SSM大学生社团管理系统【附源码数据库】
- 安装wpa_supplicant工具
- 回滚机制有多少种?它们的实现原理是什么?这些你确定都知道?
- 数商云:以数字化全面促进传统产业升级,纺织行业最大限度实现精益管理
- 最新计算机学术研讨会,TC预告|CCF 2020第十届全国文字与计算学术研讨会
- PC客户端(C/S架构)测试点整理
- Lind.DDD.Messaging框架通讯组件介绍
热门文章
- 函数分离常数法 oracle,函数值域之《分离常数法》正确打开方式
- Unity DOTS简明教程
- xp系统打印机服务器win7连接不了,xp不能访问win7共享打印机
- python 用selenium获取好友空间说说及时间写入txt
- 网站api自己怎么写_网站seo优化中文章标题怎么写?
- linux c 时间微秒,linux下C语言获取微秒级时间
- 火车头分页post php,轻松搞定PHPCMS V9火车头采集自动分页
- freeCodeCamp “使用 CSS 和 HTML 创建更复杂的形状”练习-----创建“爱心”❤️形状
- android小游戏源码拼图,android编写的数字拼图游戏(带详细注释)
- SEO快排系统功能更新