当前位置: 代码网 > it编程>前端脚本>Golang > Go语言项目中使用Viper获取配置信息详解

Go语言项目中使用Viper获取配置信息详解

2024年05月15日 Golang 我要评论
viper是go应用的完整配置解决方案,它能处理所有类型的配置需求和配置格式,支持:设置默认值。读取json、toml、yaml、hcl、envfile和java属性配置文件。实时观察和重新读取配置(

viper是go应用的完整配置解决方案,它能处理所有类型的配置需求和配置格式,支持:

  • 设置默认值。
  • 读取json、toml、yaml、hcl、envfile和java属性配置文件。
  • 实时观察和重新读取配置(可选)。
  • 读取环境变量。
  • 从远程配置系统(etcd或consul)读取配置,并观察其变化。
  • 从命令行标志读取配置。
  • 从缓冲区读取配置。
  • 设置显式值。

viper的优先级顺序是:显式调用set > 命令行标志 > 环境变量 > 配置文件 > 键/值 存储(etcd或consul) > 默认值。

本文主要记录从yaml文件、环境变量中获取配置。

使用的go的版本和viper的版本如下:

go 1.20
github.com/spf13/viper v1.18.2

从配置文件中获取配置

执行以下指令初始化项目:

go mod init github.com/rengmo/practicego

执行以下语句安装viper包:

go get github.com/spf13/viper

创建yaml文件config/dev.yaml,内容如下:

redis:
  host: localhost
  port: 6379
  user:     # 本地redis的用户名为空
  password: abc123
  db: 0

创建go文件infrastructure/config.go,内容如下:

package config

import (
	"fmt"

	"github.com/spf13/viper"
)

func init() {
	// 设置配置文件的名字
	viper.setconfigname("dev")
	// 设置文件的格式
	viper.setconfigtype("yaml")
	// 设置查找配置文件的路径为当前路径 . 表示项目的工作目录,也就是main.go同级的那个目录
	viper.addconfigpath("./config")

	// 读取配置文件中的数据到viper中
	err := viper.readinconfig()
	if err != nil {
		panic(err)
	}
	// 从viper中获取配置数据
	redisport := viper.get("redis.port")
	fmt.printf("redisport: %v \n", redisport) // 打印结果:redisport: 6379 
}

还可以使用getint()、getstring()等方法,获取指定类型的数据,viper.getstring("redis.port")就是获取字符串类型的数据。

创建main.go文件,内容如下:

package main

import (
	_ "github.com/rengmo/practicego/infrastructure"
)

func main() {

}

运行代码,会打印出获取到的端口号。

	// 设置配置文件的名字
	viper.setconfigname("dev")
	// 设置文件的格式
	viper.setconfigtype("yaml")
	// 设置查找配置文件的路径为当前路径 . 表示项目的工作目录,也就是main.go同级的那个目录
	viper.addconfigpath("./config")

换成:

// 设置配置文件的路径
viper.setconfigfile("./config/dev.yaml")

同样能取到配置文件中的数据。

除了使用get方法viper.get("redis.port")获取配置数据,还可以将配置数据反序列化成go对象。

func init() {
  ...
	var config *config
	err = viper.unmarshal(&config)
	if err != nil {
		panic(err)
	}
	redisconfig := config.redis
	fmt.printf("redisconfig %+v\n", redisconfig) 
  // 打印的结果:redisconfig {host:localhost port:6379 user: password:abc123 db:0}
}

type config struct {
	redis redisconfig
}

type redisconfig struct {
	host     string
	port     int
	user     string
	password string
	db       int
}

viper对于配置项的键是不区分大小写的,比如把yaml文件中的键改成首字母大写:

redis:
  host: localhost
  port: 6379

使用viper.get("redis.port")一样能获取到配置的值,使用viper.get("redis.port")同样能获取配置的值。

从环境变量中获取配置

automaticenv会检查环境变量中是否有和已经存在的键匹配的环境变量,如果有,就会把环境变量加载到viper中。

// automaticenv makes viper check if environment variables match any of the existing keys
// (config, default or flags). if matching env vars are found, they are loaded into viper.
func automaticenv() { v.automaticenv() }

先在终端执行指令添加环境变量: export env=prod,然后在终端执行go run .

光看这个函数名称,是自动将环境变量添加到viper中的意思,那么执行下面的语句应该就能获取环境变量,但是无效:

	viper.automaticenv()
	env := viper.get("env")
	fmt.println("env: ", env) // env:  <nil>

根据函数注释,需要确认viper中是否已经有对应的键,那么执行下面的语句应该就能获取环境变量,但是依然无效:

	viper.setdefault("env", "dev")
	viper.automaticenv()
	env := viper.get("env")
	fmt.println("env: ", env) // env:  dev

找了一下源码,判断键是否存在的地方使用了envkeys, exists := v.env[lcasekey],而bindenv方法中有设置v.env

func (v *viper) bindenv(input ...string) error {
	if len(input) == 0 {
		return fmt.errorf("missing key to bind to")
	}

	key := strings.tolower(input[0])

	if len(input) == 1 {
		v.env[key] = append(v.env[key], v.mergewithenvprefix(key))
	} else {
		v.env[key] = append(v.env[key], input[1:]...)
	}

	return nil
}

所以需要这样使用:

	viper.bindenv("env", "dev")
	viper.automaticenv()
	env := viper.get("env")
	fmt.println("env: ", env) // env:  prod

要注意在比较过程中,viper会把key转换成大写字母与环境变量进行比较,所以环境变量的名称必须为大写,不能这样设置环境变量:export env=prod,必须这样设置环境变量:export env=prod

其他

如果是使用编辑器来运行代码,需要在编辑器中设置环境变量,我用的是vscode编辑器,所以是在launch.json中添加了环境变量:

{
    // use intellisense to learn about possible attributes.
    // hover to view descriptions of existing attributes.
    // for more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "launch package",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${workspacefolder}",
            "env": {
                "env": "prod"
            }
        }
    ]
}

序列化和反序列化时,可以使用 mapstructure指定键的名称。

比如yaml文件内容:

mysql:
  host: localhost
  port: 3306
  user: root
  password: 666666aa_
  db_name: practicego

go文件内容:

type config struct {
	redis    redisconfig
	mysql    mysqlconfig
	priority string
}

type mysqlconfig struct {
	host     string
	port     int
	user     string
	password string
	dbname   string `mapstructure:"db_name"`
}

func init() {
	viper.setconfigfile("./config/dev.yaml")
	err := viper.readinconfig()
	if err != nil {
		panic(err)
	}
  
  var config *config
	err = viper.unmarshal(&config)
	if err != nil {
		panic(err)
	}
  
  mysqlconfig := config.mysql
	fmt.printf("mysqlconfig %+v\n", mysqlconfig)
}

以上就是go语言项目中使用viper获取配置信息详解的详细内容,更多关于go viper获取配置信息的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com