Go Viper 优先级问题

2 min

:construction: 配置文件中的值优先级

Viper 会按照以下优先级来加载配置,优先级从高到低:

  1. 显式调用 viper.Set
  2. 命令行参数
  3. 环境变量
  4. 配置文件
  5. viper.SetDefault

示例说明

假设有一个配置项 port,我们将分别通过五种不同的方式设置这个配置项,并观察最终的值。

1. 配置文件(config.yaml

port: 8000

2. 代码示例

package main

import (
    "flag"
    "fmt"
    "github.com/spf13/pflag"
    "github.com/spf13/viper"
    "log"
)

func init() {
    // 设置默认值
    viper.SetDefault("port", 3000)
    
    // 读取配置文件
    viper.SetConfigName("config")
    viper.SetConfigType("yaml")
    viper.AddConfigPath(".")
    if err := viper.ReadInConfig(); err != nil {
        log.Fatalf("Error reading config file: %v", err)
    }

    // 环境变量设置
    viper.BindEnv("port", "PORT")

    // 命令行参数设置
    pflag.Int("port", 4000, "Port for the application")
    pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
    pflag.Parse()
    viper.BindPFlag("port", pflag.Lookup("port"))

    // 显式设置
    viper.Set("port", 5000)
}

func main() {
    port := viper.GetInt("port")
    fmt.Printf("The application port is: %d\n", port)
}

设置与输出

1. 配置文件中的值

config.yaml 文件中设置 port8000

port: 8000

2. 环境变量

在运行程序前设置环境变量 PORT

export PORT=7000

3. 命令行参数

通过命令行参数传递 port

go run main.go --port=6000

4. 显式设置

在代码中显式调用 viper.Set("port", 5000)

5. 设置默认值

在代码中调用 viper.SetDefault("port", 3000)

执行顺序

  1. 显式调用 viper.Set("port", 5000):显式设置 port5000
  2. 命令行参数 --port=6000:命令行参数设置 port6000
  3. 环境变量 PORT=7000:环境变量设置 port7000
  4. 配置文件 port: 8000:配置文件设置 port8000
  5. 默认值 viper.SetDefault("port", 3000):默认值设置 port3000

运行结果

运行程序时,由于优先级顺序,最终输出会是显式调用 viper.Set("port", 5000) 的值,即:

The application port is: 5000