golang使用viper库读取配置文件

一、viper简介

1.1 viper简介

Viper是适用于Go应用程序的完整配置解决方案。它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式。

1.2 viper获取方式

go get github.com/spf13/viper

1.3 viper的常用API

//设置默认值示例
viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
//读取配置文件示例
viper.SetConfigFile("./config.yaml") // 指定配置文件路径
viper.SetConfigName("config") // 配置文件名称(无扩展名)
viper.SetConfigType("yaml") // 如果配置文件的名称中没有扩展名,则需要配置此项
viper.AddConfigPath("/etc/appname/")   // 查找配置文件所在的路径
viper.AddConfigPath("$HOME/.appname")  // 多次调用以添加多个搜索路径
viper.AddConfigPath(".")               // 还可以在工作目录中查找配置
err := viper.ReadInConfig() // 查找并读取配置文件
if err := viper.ReadInConfig(); err != nil {
    if _, ok := err.(viper.ConfigFileNotFoundError); ok {
        // 配置文件未找到错误;如果需要可以忽略
    } else {
        // 配置文件被找到,但产生了另外的错误
    }
}
// 获取值的方法
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
IsSet(key string) : bool
AllSettings() : map[string]interface{}

//反序列化方法
Unmarshal(rawVal interface{}) : error
UnmarshalKey(key string, rawVal interface{}) : error

二、viper读取配置文件示例

下面通过写一个公用的工具文件ViperConfigUtil.go和UT测试ViperConfigUtil_test.go,来说明读取不同配置文件的使用方法

2.1 读取配置文件的通用方法

首先我们在ViperConfigUtil.go中写一个通用的读取配置文件的方法,方法传入文件路径,名称和类型为参数,返回一个Viper的指针,用来获取文件

/**
 * 通用的读取配置文件的方法,传入路径和文件名以及类型,返回一个Viper的指针
 */
func readFile(filePath, fileName, configType string) (config *viper.Viper, err error) {
	config = viper.New()
	config.AddConfigPath(filePath)
	config.SetConfigName(fileName)
	config.SetConfigType(configType)
	if err := config.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			fmt.Println("Not found config file")
		} else {
			fmt.Printf("read config file error, %v \n", err)
		}
	}
	return
}

接下来,我们分别写读取ini、json和yaml等不同类型配置文件的方法

// ReadIniConfig 读取ini类型配置文件
func ReadIniConfig(filePath, fileName string) (*viper.Viper, error) {
	return readFile(filePath, fileName, "ini")
}

// ReadJsonConfig 读取json类型配置文件
func ReadJsonConfig(filePath, fileName string) (*viper.Viper, error) {
	return readFile(filePath, fileName, "json")
}

// ReadJsonConfigAndTransToStruct 读取json配置文件并转成制定的结构体
func ReadJsonConfigAndTransToStruct(filePath, fileName string, value any) error {
	config, err := ReadJsonConfig(filePath, fileName)
	if err != nil {
		return err
	}
	return config.Unmarshal(value)
}

// ReadYamlConfig 读取yaml类型配置文件
func ReadYamlConfig(filePath, fileName string) (*viper.Viper, error) {
	return readFile(filePath, fileName, "yaml")
}

下面我们就在UT文件ViperConfigUtil_test.go中测试如何使用viper读取配置文件

2.2 读取ini配置文件

首先我们在项目./config/目录下新建一个iniConfig.ini文件,其内容如下:

[mysql]
username='root'
password='123456'

[redis]
host='127.0.0.1'
poet=3306

[mongodb]
user='admin'
password='admin'

编写读取ini文件的测试方法

func TestReadIniConfig(t *testing.T) {
	fmt.Println("TestReadIniConfig")
	config, err := ReadIniConfig(utils.GetCurrentDirectory()+"/config/", "iniConfig")
	if err != nil {
		fmt.Printf("read config error,%v \n", err)
		return
	}
	fmt.Printf("mysql.username=%v \n", config.Get("mysql.username"))
	fmt.Printf("redis.host=%v \n", config.Get("redis.host"))
	fmt.Printf("mongodb.user=%v \n", config.Get("mongodb.user"))
	fmt.Printf("mongodb.password=%v \n", config.Get("mongodb.password"))
}

运行结果如下:

=== RUN   TestReadIniConfig
TestReadIniConfig
mysql.username=root 
redis.host=127.0.0.1 
mongodb.user=admin 
mongodb.password=admin 
--- PASS: TestReadIniConfig (0.00s)
PASS


Process finished with the exit code 0

2.3 读取json配置文件

首先我们在项目./config/目录下新建一个jsonConfig.json文件,其内容如下:

{
  "version": "2.0",
  "secret": "footmark",
  "host": {
    "origin": "http://www.baidu.com",
    "port": 8080
  }
}

编写读取json文件的测试方法:

func TestReadJsonConfig(t *testing.T) {
	fmt.Println("TestReadJsonConfig")
	config, err := ReadJsonConfig(utils.GetCurrentDirectory()+"/config/", "jsonConfig")
	if err != nil {
		fmt.Printf("read config error,%v \n", err)
		return
	}
	fmt.Printf("version=%v \n", config.Get("version"))
	fmt.Printf("secret=%v \n", config.Get("secret"))
	fmt.Printf("host.origin=%v \n", config.Get("host.origin"))
	fmt.Printf("host.port=%v \n", config.Get("host.port"))
}

运行结果如下:

=== RUN   TestReadJsonConfig
TestReadJsonConfig
version=2.0 
secret=footmark 
host.origin=http://www.baidu.com 
host.port=8080 
--- PASS: TestReadJsonConfig (0.00s)
PASS


Process finished with the exit code 0

2.4 读取json配置文件并转换成对象

我们读取了json后,很多时候希望将其转换成对象的方式,现在就以上面的json文件为例,编写两个结构体对象,并编写测试方法,代码如下:

type JsonStruct struct {
	Version string     `json:version`
	Secret  string     `json:secret`
	Host    HostStruct `json:"host"`
}

type HostStruct struct {
	Origin string `json:origin`
	Port   int    `json:port`
}

func TestReadJsonConfigAndTransToStruct(t *testing.T) {
	fmt.Println("TestReadJsonConfigAndTransToStruct")
	var jsonStruct JsonStruct
	err := ReadJsonConfigAndTransToStruct(utils.GetCurrentDirectory()+"/config/", "jsonConfig", &jsonStruct)
	if err != nil {
		fmt.Printf("read config error,%v \n", err)
		return
	}
	fmt.Printf("version=%v \n", jsonStruct.Version)
	fmt.Printf("secret=%v \n", jsonStruct.Secret)
	fmt.Printf("host.origin=%v \n", jsonStruct.Host.Origin)
	fmt.Printf("host.port=%v \n", jsonStruct.Host.Port)
}

运行结果如下:

=== RUN   TestReadJsonConfigAndTransToStruct
TestReadJsonConfigAndTransToStruct
version=2.0 
secret=footmark 
host.origin=http://www.baidu.com 
host.port=8080 
--- PASS: TestReadJsonConfigAndTransToStruct (0.00s)
PASS


Process finished with the exit code 0

2.5 读取yaml配置文件

首先我们在项目./config/目录下新建一个yamlConfig.yaml文件,其内容如下:

database:
  host: 127.0.0.1
  user: root
  dbname: test
  pwd: 123456

编写读取文件的测试方法:

func TestReadYamlConfig(t *testing.T) {
	fmt.Println("TestReadYamlConfig")
	config, err := ReadYamlConfig(utils.GetCurrentDirectory()+"/config/", "yamlConfig")
	if err != nil {
		fmt.Printf("read config error,%v \n", err)
		return
	}
	fmt.Printf("database.host=%v \n", config.Get("database.host"))
	fmt.Printf("database.user=%v \n", config.Get("database.user"))
	fmt.Printf("database.dbname=%v \n", config.Get("database.dbname"))
	fmt.Printf("database.pwd=%v \n", config.Get("database.pwd"))
}

运行结果如下:

=== RUN   TestReadYamlConfig
TestReadYamlConfig
database.host=127.0.0.1 
database.user=root 
database.dbname=test 
database.pwd=123456 
--- PASS: TestReadYamlConfig (0.00s)
PASS


Process finished with the exit code 0

2.6 代码说明

  • 1 示例中的GetCurrentDirectory()方法是用来读取编译到的程序的运行目录,是自己写的一个util方法,其代码如下:
func GetCurrentDirectory() string {
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		fmt.Printf("get path error. %v", err)
		return dir
	}
	return strings.Replace(dir, "\\", "/", -1)
}
  • 2 如果运行当中报配置文件找不到,大概率是因为我们编译的输出路径和配置文件路径不一致,需要编辑一下运行的Output directory,将输出路径和代码路径写成一致,就可以了

路径配置


后记
  个人总结,欢迎转载、评论、批评指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值