Viper 自动环境不从环境中读取

问题描述

我正在尝试完成一个非常简单的示例,其中我使用 viper 从环境变量加载配置。我已通过 go get github.com/spf13/viper 将其安装在我的项目中,并且依赖项在我的 go.mod 中:

module github.com/naftulikay/viper-demo

go 1.16

require github.com/spf13/viper v1.7.1 // indirect

这是我的代码,它可以编译并运行:

package main

import (
    "fmt"
    "github.com/spf13/viper"
)

var config Config

type Config struct {
    MyString string //`mapstructure:"MY_STRING"`
}

func main() {
    v := viper.New()
    v.AutomaticEnv()

    var err error

    err = v.Unmarshal(&config)

    if err != nil {
        fmt.Printf("Unable to load config: %s\n",err)
    }

    fmt.Printf("%+v\n",&config)
}

我正在设置环境变量以尝试测试环境变量名称的不同排列

MY_STRING=a my_string=b MyString=c ./viper-demo

我尝试了很多不同的方法删除 mapstructure 注释,更改其值等,但我执行时得到的只是:

&{MyString:}

我正在按照自述文件以及我在网上找到的其他演示中的说明进行操作,但似乎 viper 不会加载环境变量。

我觉得这是一个非常简单的例子,我的要求是将配置映射到一个结构体,并从环境变量中获取该配置。我最终可能会开始做 CLI 标志和配置文件,但环境变量对我来说是成败的,我需要它们才能工作。

我错过了什么?

解决方法

这似乎是一个长期存在的问题,已经持续了好几年 [1]。然而,在 该线程建议您可以使用 BindEnv [2]:

package main

import (
    "fmt"
    "github.com/spf13/viper"
)

func main() {
   var c struct {
      TMP string
   }
   v := viper.New()
   v.AutomaticEnv()
   v.BindEnv("TMP")
   v.Unmarshal(&c)
   fmt.Printf("%+v\n",&c)
}

对于另一种方法,您可以使用 os.Environ [3]:

package main

import (
   "fmt"
   "os"
   "strings"
)

func environ() map[string]string {
   m := make(map[string]string)
   for _,s := range os.Environ() {
      a := strings.Split(s,"=")
      m[a[0]] = a[1]
   }
   return m
}

func main() {
   m := environ()
   fmt.Printf("%q\n",m)
}
  1. https://github.com/spf13/viper/issues/188
  2. https://pkg.go.dev/github.com/spf13/viper#Viper.BindEnv
  3. https://golang.org/pkg/os#Environ