Viper 大中型项目配置解析神器

Viper 大中型项目配置解析神器

1.简介

1.1 功能

  • 支持JSON,TOML,YAML,Java propertoes等多种不同类型配置文件。
  • 支持配置key值默认值,且不区分大小写
  • 读取系统环境变量等方式

1.2 配置优先级

viper支持从多个数据源读取配置值,因此当同一个配置key在多个数据源有值时,需要一定的优先级:

image-20240421152152368

  • Set:使用Set函数设置值
  • flag:命令行参数
  • env:环境变量
  • config:配置文件
  • key/value store:k-v存储系统,eg:ectd
  • default:默认值

1.3 安装viper

go get github.com/spf13/viper
import "github.com/spf13/viper"

1.4 支持格式

jsontomlyamlymlpropertiesprops
prophcltfvarsdontenvenvini

2 viper 使用

2.1 默认值和配置文件读取

func main() {
	v := viper.New()
	// 设置默认值
	v.SetDefault("key1", "value1")
	fmt.Printf("默认值 key1= %s \n", v.Get("key1"))
	// 读取配置文件
	v.SetConfigFile("./config.yml")
	v.ReadInConfig()
	fmt.Printf("读取配置文件 key2= %s \n", v.Get("key2"))
	fmt.Printf("读取配置文件 key1= %s \n", v.Get("key1"))
}

image-20240421160702061

2.2 多路径查找

viper.SetConfigName("config")     // 配置文件名,不需要后缀名
viper.SetConfigType("yml")            // 配置文件格式
viper.AddConfigPath("/etc/appname/")  // 查找配置文件的路径
viper.AddConfigPath("$HOME/.appname") // 查找配置文件的路径
viper.AddConfigPath(".")              // 查找配置文件的路径
err := viper.ReadInConfig()           // 查找并读取配置文件
if err != nil {                       // 处理错误
    if_, ok := err.(viper.ConfigFileNotFoundError); ok { // 如果错误是因为找不到文件的报错
        
    }else{
        panic(fmt.Errorf("Fatal error config file: %w \n", err))
    }
}

2.3 写配置文件

// 写配置文件
	v.AddConfigPath(".")
	v.SetConfigName("config")
	// WriteConfig 将配置写入预先设置好路径的配置文件中,如果配置文件存在,则覆盖,如果没有,则创建。
	v.Set("key3", "value3")
	v.WriteConfig()
	// SafeWriteConfig 与WriteConfig函数唯一的不同是如果配置文件存在,则会返回一个错误。
	v.Set("key3", "value3")
	if err := v.SafeWriteConfig(); err != nil {
		fmt.Println(err)
	}
	// WriteConfigAs 与WriteConfig函数的不同是需要传入配置文件保存路径,viper会根据文件后缀判断写入格式。
	v.Set("key4", "value4")
	v.WriteConfigAs("config.yml")
	// SafeWriteConfigAs 与WriteConfigAs的唯一不同是如果配置文件存在,则返回一个错误。
	v.Set("key5", "value5")
	if err := v.SafeWriteConfigAs("config.yml"); err != nil {
		fmt.Println(err)
	}

image-20240421162636099

config.yml

image-20240421162648176

v.SafeWriteConfigAs("config.yml")改为yaml文件

config.yaml

image-20240421162851077

2.4 监控并重新读取配置文件

	// 在监控之前要添加要监控的文件或路径
	v.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("config file changed:", in.Name)
	})
	fmt.Printf("读取配置文件 key4= %s \n", v.Get("key4"))
	v.WatchConfig()
	// 趁这期间修改配置文件
	for i := 0; i < 10; i++ {
		time.Sleep(time.Second) 
	}
	fmt.Printf("读取配置文件 key4= %s \n", v.Get("key4"))
读取配置文件 key4= value5
config file changed: config.yml
config file changed: config.yml
读取配置文件 key4= value4

2.5 注册别名

viper.RegisterAlias("key1","key")

之后可以直接操作别名,修改会作用到原本的配置项上。

3 访问配置

{
  "mysql":{
    "db":"test"
  },
  "host":{
	  "address":"localhost"
	  "ports":[
		  "8080",
		  "8081"
	  ]
  }
}

直接访问:

viper.Get("mysql.db")

viper.GetString("user.db")

viper.Get("host.address")//输出:localhost

viper.Get("host.posts.1")//输出: 8081

分级读取

hostViper := viper.Sub("host")
fmt.Println(hostViper.Get("address"))
fmt.Println(hostViper.Get("posts.1"))

访问函数:

  • Get(key string) : interface{}
  • GetBool(key string) : bool
  • GetFloat64(key string) : float64
  • GetInt(key string) : int
  • GetIntSlice(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

3.1 序列化

config.yaml

host: localhost
username: test
password: test
port: 3306
charset: utf8
dbName: test
type MySQL struct {
	Host     string
	DbName   string
	Port     string
	Username string
	Password string
	Charset  string
}

func main() {

	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath(".")
	viper.ReadInConfig()
	var mysql MySQL

	viper.Unmarshal(&mysql)//序列化

	fmt.Println(mysql.Username)
	fmt.Println(mysql.Host)
}
// console
test
localhost

多层级配置

mysql: 
  host: localhost
  username: test
  password: test
  port: 3306
  charset: utf8
  dbName: test
redis: 
  host: localhost
  port: 6379

type MySQL struct {
	Host     string
	DbName   string
	Username string
	Password string
	Charset  string
}

type Redis struct {
	Host string
	Port string
}

type Config struct {
	MySQL MySQL
	Redis Redis
}

func main() {

	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath(".")
	viper.ReadInConfig()
	var config Config

	viper.Unmarshal(&config)

	fmt.Println(config.MySQL.Username)
	fmt.Println(config.Redis.Host)
}

3.2 查看key是否存在

if viper.IsSet("user"){
	fmt.Println("key user is not exists")
}

3.3 打印所有配置

m := viper.AllSettings()
fmt.Println(m)

参考链接:

Go项目配置管理工具—Viper

Go语言配置管理神器——Viper中文教程

Golang名库观止 | 配置解析神器viper使用详解

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值