【问题标题】:Reading in environmental Variable Using Viper Go使用 Viper Go 读取环境变量
【发布时间】:2020-11-24 20:32:54
【问题描述】:

我试图让 Viper 读取我的环境变量,但它不起作用。这是我的配置:

# app.yaml
dsn: RESTFUL_APP_DSN
jwt_verification_key: RESTFUL_APP_JWT_VERIFICATION_KEY
jwt_signing_key: RESTFUL_APP_JWT_SIGNING_KEY
jwt_signing_method: "HS256"

还有我的config.go 文件:

package config

import (
    "fmt"
    "strings"

    "github.com/go-ozzo/ozzo-validation"
    "github.com/spf13/viper"
)

// Config stores the application-wide configurations
var Config appConfig

type appConfig struct {
    // the path to the error message file. Defaults to "config/errors.yaml"
    ErrorFile string `mapstructure:"error_file"`
    // the server port. Defaults to 8080
    ServerPort int `mapstructure:"server_port"`
    // the data source name (DSN) for connecting to the database. required.
    DSN string `mapstructure:"dsn"`
    // the signing method for JWT. Defaults to "HS256"
    JWTSigningMethod string `mapstructure:"jwt_signing_method"`
    // JWT signing key. required.
    JWTSigningKey string `mapstructure:"jwt_signing_key"`
    // JWT verification key. required.
    JWTVerificationKey string `mapstructure:"jwt_verification_key"`
}

func (config appConfig) Validate() error {
    return validation.ValidateStruct(&config,
        validation.Field(&config.DSN, validation.Required),
        validation.Field(&config.JWTSigningKey, validation.Required),
        validation.Field(&config.JWTVerificationKey, validation.Required),
    )
}

func LoadConfig(configpaths ...string) error {
    v := viper.New()
    v.SetConfigName("app")
    v.SetConfigType("yaml")
    v.SetEnvPrefix("restful")
    v.AutomaticEnv()
    v.SetDefault("error_file", "config/errors.yaml")
    v.SetDefault("server_port", 1530)
    v.SetDefault("jwt_signing_method", "HS256")
    v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

    for _, path := range configpaths {
        v.AddConfigPath(path)
    }

    if err := v.ReadInConfig(); err != nil {
        return fmt.Errorf("Failed to read the configuration file: %s", err)
    }

    if err := v.Unmarshal(&Config); err != nil {
        return err
    }

    // Checking with this line. This is what I get:
    // RESTFUL_JWT_SIGNING_KEY
    fmt.Println("Sign Key: ", v.GetString("jwt_signing_key"))

    return Config.Validate()
}

fmt.Println("Sign Key: ", v.GetString("jwt_signing_key")) 这一行只给了我在 yaml 文件 RESTFUL_JWT_SIGNING_KEY 中传递的密钥。我不知道我做错了什么。

根据文档:

AutomaticEnv 是一个强大的助手,尤其是与 设置环境前缀。调用时,Viper 将检查环境 随时发出 viper.Get 请求时的变量。它将应用 遵循规则。它将检查具有名称的环境变量 如果设置了 EnvPrefix,则匹配大写和前缀的键。

那么,它为什么不读取环境变量呢?

使用JSON

{
  "dsn": "RESTFUL_APP_DSN",
  "jwt_verification_key": "RESTFUL_APP_JWT_VERIFICATION_KEY",
  "jwt_signing_key": "RESTFUL_APP_JWT_SIGNING_KEY",
  "jwt_signing_method": "HS256"
}

我的解析器看起来像这样:

// LoadConfigEnv loads configuration from the given list of paths and populates it into the Config variable.
// Environment variables with the prefix "RESTFUL_" in their names are also read automatically.
func LoadConfigEnv(environment string, configpaths ...string) error {
  v := viper.New()
  v.SetConfigName(environment)
  v.SetConfigType("json")
  v.SetEnvPrefix("restful")
  v.AutomaticEnv()
  v.SetDefault("jwt_signing_method", "HS256")
  v.SetDefault("error_file", "config/errors.yaml")
  v.SetDefault("server_port", 1530)
  v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

  for _, path := range configpaths {
    v.AddConfigPath(path)
  }

  if err := v.ReadInConfig(); err != nil {
    return fmt.Errorf("Failed to read the configuration file: %s", err)
  }

  if err := v.Unmarshal(&Config); err != nil {
    return err
  }

  return Config.Validate()
}

Validate 函数中,我决定检查Config 结构,这就是我得到的:

Config: {config/errors.yaml 1530 RESTFUL_APP_DSN HS256 RESTFUL_APP_JWT_SIGNING_KEY RESTFUL_APP_JWT_VERIFICATION_KEY}

【问题讨论】:

  • 无法重现:play.golang.org/p/YvK__C7zx13 $ RESTFUL_JWT_SIGNING_KEY=from-env go run main.go 输出“签名密钥:from-env”。
  • fmt.Printf("Getenv: %q\n", os.Getenv("RESTFUL_JWT_SIGNING_KEY")) 添加到您的程序中,让我们知道打印的内容。
  • @Peter 当我这样做时,它会获取环境变量的值Getenv: "QfCAH04Cob7b71QCqy738vw5XGSnFZ9d"
  • 你是如何运行它的?你能确定你使用的是最新版本的 viper 吗?
  • @TarunLalwani 是的。我是。检查上面,我决定把它改成JSON文件,还是一样的。

标签: go viper-go


【解决方案1】:

我的问题中的代码实际上并没有显示我想要解决的问题。在了解了问题所在之后,我相信这里的代码会在我的开发环境中本地运行。

根据Viper documentation

AutomaticEnv 是一个强大的助手,尤其是与 SetEnvPrefix 结合使用时。调用时,Viper 将在任何时候发出 viper.Get 请求时检查环境变量。它将应用以下规则。它将检查名称与大写键匹配的环境变量,如果设置了 EnvPrefix 前缀。

这句话说明了一切:

它将检查名称与键名匹配的环境变量(如果设置了则以大写字母和 EnvPrefix 为前缀)

使用v.SetEnvPrefix("restful") 设置的前缀将期望.yaml 的键值为:

示例 app.yaml:

dsn: RESTFUL_DSN

注意 DSN 是 小写的密钥,它被用作 SuffixRESTFUL_DSN

在我的情况下,我是这样做的:

示例 app.yaml:

dsn: RESTFUL_APP_DSN

所以,它在我的环境中检查 RESTFUL_DSN 而不是 RESTFUL_APP_DSN

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    • 2020-01-16
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 2017-03-06
    相关资源
    最近更新 更多