viper
https://github.com/spf13/viper
Install
go get github.com/spf13/viper
Use
ENV文件
编写env文件的规范:
- 全大写的下划线命名法, 例如
DB_SOURCE
- Key与Value使用
=
赋值, 中间没有任何空格 - Value值内容无需引号
DB_SOURCE=postgresql://postgres:postgres@localhost:5432/simple_bank?sslmode=disable
SEVER_ADDRESS=localhost:8080
go代码:
// 将struct的字段与env配置文件的Key通过mapstructure这个tag对应起来
type Config struct {
DBSource string `mapstructure:"DB_SOURCE"`
ServerAddress string `mapstructure:"SEVER_ADDRESS"`
}
func LoadConfig(path string) (cfg *Config, err error) {
// 传入配置文件的文件名
viper.SetConfigName("app") // name of config file (without extension)
// 传入配置文件的后缀
viper.SetConfigType("env") // REQUIRED if the config file does not have the extension in the name
// 传入配置文件与运行的go文件的相对路径
viper.AddConfigPath(path) // 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: %w", err))
}
// 自动从环境变量替换配置文件的值
viper.AutomaticEnv()
// 将得到的配置文件进行解构
err = viper.Unmarshal(&cfg)
if err != nil {
return
}
return
}
func main() {
cfg, err := config.LoadConfig(".")
if err != nil {
panic(err)
}
conn, err := pgxpool.New(context.Background(), cfg.DBSource)
if err != nil {
panic(fmt.Sprintf("Unable to connect to database: %v", err))
}
store := db.NewStore(conn)
server := api.NewServer(store)
err = server.Start(cfg.ServerAddress)
}
环境变量的优先级是大于配置文件的. 测试环境变量是否可以覆盖env文件的值, 如果运行的结果是环境变量的值, 则viper正常工作
SEVER_ADDRESS=localhost:8081 go run main
Yaml
- 文件类型, viper支持多种文件类型
viper.SetConfigType("yaml")
- 文件路 径
viper.SetConfigFile("./config.yaml")
- 读取
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: %w", err))
}
获取
- GetString: 获取字段并转成字符串
httpAddr := viper.GetString("server.http.addr")
设置
更新与添加是一样的方法, 区别在于, 如果源文件没有的字段会自动添加, 源文件有的字段会更新它的值
- 添加新字段与新值
viper.Set("new_field", "new_value")
- 更新新值
viper.Set("server.http.addr", "new_http_addr")
示例1:
func main() {
// 初始化Viper
viper.SetConfigFile("config.yaml") // 配置文件的文件名
viper.SetConfigType("yaml") // 配置文件的类型(YAML)
// 读取配置文件
if err := viper.ReadInConfig(); err != nil {
fmt.Printf("Error reading config file: %v\n", err)
return
}
// 读取字段值
httpAddr := viper.GetString("server.http.addr")
grpcAddr := viper.GetString("server.grpc.addr")
fmt.Printf("HTTP Addr: %s\n", httpAddr)
fmt.Printf("GRPC Addr: %s\n", grpcAddr)
// 修改字段值
viper.Set("server.http.addr", "new_http_addr")
viper.Set("server.grpc.addr", "new_grpc_addr")
// 添加新字段
viper.Set("new_field", "new_value")
// 写入配置文件(保存修改后的配置)
if err := viper.WriteConfig(); err != nil {
fmt.Printf("Error writing config file: %v\n", err)
return
}
fmt.Println("Config file updated successfully.")
}
示例2: 解析配置文件
func GetPath(file, dir string) string {
if dir == "" {
dir = "/config/"
}
_, filename, _, _ := runtime.Caller(0)
root := path.Dir(path.Dir(filename)) //获取当前工作目录
dirPath := path.Dir(root + dir) // 获取配置文件的目录
filePath := path.Join(dirPath, file) // 获取配置文
return filePath
}
filePath := utils.GetPath("db.yaml", "")
fmt.Println("filePath:", filePath)
viper.SetConfigFile(filePath) // 给viper读取文件的路径
readErr := viper.ReadInConfig()
if readErr != nil {
log.Fatalln("读取配置文件失败")
}
username := viper.GetString("mongodb.username") // 解析mongodb配置的用户名(如果对数据库设置了密码)
password := viper.GetString("mongodb.password") // 解析mongodb配置的密码(如果对数据库设置了密码)
uri := viper.GetString("mongodb.uri") // 解析mongodb配置的链接