配置文件viper库

1 viper概述

viper是Go应用程序的完整配置解决方案。在构建现代化应用程序的过程中,开发人员可以通过使用viper而不必考虑配置文件的格式问题,可以被认为是所有应用程序配置需求的注册表。它支持功能:

  • 设置默认值
  • 从JSON,TOML,YAML,HCL和Java属性配置文件中读取
  • 实时观看和重新读取配置文件(可选)
  • 从环境变量中读取
  • 从远程配置系统(etcd或Consul)读取,并观察变化
  • 从命令行标志读取
  • 从缓冲区读取
  • 设置显式值


viper提供的配置方式的优先级顺序如下(由高到低):

  • (1) 设置显示调用(explicit call to Set)
  • (2) 命令行标志(flag)
  • (3) 环境变量(env)
  • (4) 配置文件(config)
  • (5) 远程键/值存储(key/value store)
  • (6) 默认值(default)

viper支持在运行时让应用程序实时读取配置文件,使应用程序一直使用最新修改的配置文件,从而不需要再重启服务。



2 解析常用配置文件示例

示例展示读取yaml、toml、json配置到对象,并且实时监听更新配置文件变化。

文件目录如下:

.
├── conf.go
├── conf_test.go
├── conf.json
├── conf.toml
└── conf.yaml


yaml格式配置文件conf.yaml内容如下:

# 服务名称
serverName: "my server"
# 监听地址
serverPort: 8080
# 运行模式,dev:开发环境,prod:正式环境
runMode: "dev"

# 是否开启性能分析功能,true:开启,false:关闭
isEnableProfile: true

# 输出日志级别 debug, info, warn, error
logLevel: "debug"

# Etcd集群地址
etcdEndpoints:
  - "127.0.0.1:23791"
  - "127.0.0.1:23792"
  - "127.0.0.1:23793"

# mysql配置
mysqlURL: "root:123456@(127.0.0.1:3306)/user?charset=utf8&parseTime=true"

# mongodb配置
mongoURL: "mongodb://test:123456@127.0.0.1:27017/test"

# redis配置
redis:
  addr: "127.0.0.1:6379"
  password: "123456"
  db: 0

# 字典
servers:
  Beijing:
    addr: "127.0.0.1"
    port: "20060"
  Shanghai:
    addr: "127.0.0.1"
    port: "20061"


toml格式配置文件conf.toml内容如下:

# 服务名称
serverName = "my server"
# 监听地址
serverPort = 8080
# 运行模式,dev:开发环境,prod:正式环境
runMode = "dev"

# 是否开启性能分析功能,true:开启,false:关闭
isEnableProfile = true

# 输出日志级别 debug, info, warn, error
logLevel = "debug"

# Etcd集群地址
etcdEndpoints = ["127.0.0.1:23791", "127.0.0.1:23792", "127.0.0.1:23793"]

# mysql配置
mysqlURL = "root:123456@(127.0.0.1:3306)/user?charset=utf8&parseTime=true"

# mongodb配置
mongoURL = "mongodb://test:123456@127.0.0.1:27017/test"

# redis配置
[redis]
    addr = "127.0.0.1:6379"
    password = "123456"
    db = 0

# 字典
[servers]
    [servers.Beijing]
        addr = "127.0.0.1"
        port = "20060"
    [servers.Shanghai]
        addr = "127.0.0.1"
        port = "20061"


json格式配置文件conf.json内容如下:

{
    "serverName":"my server",
    "serverPort":8080,
    "runMode":"dev",
    "isEnableProfile":true,
    "logLevel":"debug",
    "etcdEndpoints":[
        "127.0.0.1:23791",
        "127.0.0.1:23792",
        "127.0.0.1:23793"
    ],
    "mysqlURL":"root:123456@(127.0.0.1:3306)/user?charset=utf8&parseTime=true",
    "mongoURL":"mongodb://test:123456@127.0.0.1:27017/test",
    "redis":{
        "addr":"127.0.0.1:6379",
        "password":"123456",
        "db":0
    },
    "servers":{
        "Beijing":{
            "addr":"127.0.0.1",
            "port":"20060"
        },
        "Shanghai":{
            "addr":"127.0.0.1",
            "port":"20061"
        }
    }
}


解析配置文件conf.go内容如下:

package config

import (
    "path"
    "strings"

    "github.com/spf13/viper"
)

var conf = new(Conf)

// Conf 服务配置信息
type Conf struct {
    // 服务名称
    ServerName string `json:"serverName" toml:"serverName"`
    // 服务端口
    ServerPort int `json:"serverPort" toml:"serverPort"`
    // 运行模式
    RunMode string `json:"runMode" toml:"runMode"`

    // 是否开启go profile
    IsEnableProfile bool `json:"isEnableProfile" toml:"isEnableProfile"`

    // 输出日志级别
    LogLevel string `json:"logLevel" toml:"logLevel"`

    // Etcd集群地址
    EtcdEndpoints []string `json:"etcdEndpoints" toml:"etcdEndpoints"`

    // mysql配置
    MysqlURL string `json:"mysqlURL" toml:"mysqlURL"`

    // mongodb配置
    MongoURL string `json:"mongoURL" toml:"mongoURL"`

    // redis配置
    Redis *RedisConf `json:"redis" toml:"redis"`

    // log配置
    Servers map[string]*Servers `json:"servers" toml:"servers"`
}

// RedisConf Redis配置信息
type RedisConf struct {
    Addr     string `json:"addr" toml:"addr"`
    Password string `json:"password" toml:"password"`
    DB       int    `json:"db" toml:"db"`
}

// Servers 服务地址
type Servers struct {
    Addr string `json:"addr" toml:"addr"`
    Port string `json:"port" toml:"port"`
}

// Get 获取配置对象
func Get() *Conf {
    return conf
}

// ParseConfig 解析配置文件到对象,包括yaml、toml、json等文件
func ParseConfig(filePath string, fileName string) error {
    viper.AddConfigPath(filePath)                                  // 路径
    viper.SetConfigName(fileName)                                  // 名称
    viper.SetConfigType(strings.TrimLeft(path.Ext(fileName), ".")) // 从文件名中获取配置类型

    err := viper.ReadInConfig()
    if err != nil {
        return err
    }

    err = viper.Unmarshal(conf)
    if err != nil {
        return err
    }

    // 监听配置文件更新
    viper.WatchConfig()
    viper.OnConfigChange(func(e fsnotify.Event) {
        viper.Unmarshal(conf)
    })

    return nil
}


conf_test.go文件内容如下:

package config

import (
    "testing"

    "github.com/k0kubun/pp"
)

func TestParseYAML(t *testing.T) {
    err := ParseConfig("./", "conf.yaml") // 解析yaml文件
    if err != nil {
        t.Error(err)
        return
    }

    pp.Println(Get())
}

func TestParseTOML(t *testing.T) {
    err := ParseConfig("./", "conf.toml") // 解析toml文件
    if err != nil {
        t.Error(err)
        return
    }

    pp.Println(Get())
}

func TestParseJSON(t *testing.T) {
    err := ParseConfig("./", "conf.json") // 解析json文件
    if err != nil {
        t.Error(err)
        return
    }

    pp.Println(Get())
}

// 测试更新配置文件
func TestWatch(t *testing.T) {
    err := ParseConfig("./", "conf.yaml")
    if err != nil {
        t.Error(err)
        return
    }

    for i := 0; i < 30; i++ {
        fmt.Println("port:", Get().ServerPort)
        time.Sleep(time.Second)
    }
}

经过测试,yaml、toml、json这三个文件解析结果都是一致的。


参考:https://blog.csdn.net/cs380637384/article/details/81217767



专题「golang相关」的其它文章 »