viper
https://github.com/spf13/viper
Install
go get github.com/spf13/viperUse
ENV文件
编写env文件的规范:
- 全大写的下划线命名法, 例如
DB_SOURCE - Key与Value使用
=赋值, 中间没有任何空格 - Value值内容无需引号
DB_SOURCE=postgresql://postgres:postgres@localhost:5432/simple_bank?sslmode=disableSEVER_ADDRESS=localhost:8080go代码:
// 将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 mainYaml
- 文件类型, viper支持多种文件类型
viper.SetConfigType("yaml")- 文件路径
viper.SetConfigFile("./config.yaml")- 读取
err := viper.ReadInConfig() // Find and read the config fileif 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配置的链接