使用 viper 从 envfile 读取配置

xN0*_*31x 6 go viper-go

我不太明白 viper 是如何工作的。这是我的代码:

配置.go

var Config *Configuration

type ServerConfiguration struct {
    Port string
}

type Configuration struct {
    Server   ServerConfiguration
}

func Init() {
    var configuration *Configuration
    viper.SetConfigFile(".env")
    viper.AutomaticEnv()
    if err := viper.ReadInConfig(); err != nil {
        log.Fatalf("Error reading config file, %s", err)
    }

    err := viper.Unmarshal(&configuration)
    if err != nil {
        log.Fatalf("Unable to decode into struct, %v", err)
    }

    Config = configuration
}

func GetConfig() *Configuration {
    return Config
}
Run Code Online (Sandbox Code Playgroud)

.env SERVER_PORT=:4747

问题是 Unmarshal 不起作用当我使用例如配置时。Server.Port 它是空的

Ini*_*ian 4

spf13/viper主要使用MapStructure包在一种本机 Go 类型之间转换为另一种类型,即在解组时。该包内部使用map[string]interface{}type 来存储您的配置(请参阅viper.go - L1327)。之后,根据配置类型(您的情况是env),viper 调用正确的解析包来存储您的配置值。对于 envfile 类型,它使用subosito/gotenv放入上述映射类型(参见viper.go - L1501

问题的关键是如何让 viper 将映射中的配置解组到您选择的结构。这就是 MapStructure 包的用武之地,它将映射解组到您定义的嵌套结构中。此时你有两个选择

  1. 将配置解组为map[string]interface{}类型,然后使用映射结构放入适当的结构
  2. 使用DecodeHookFunc作为方法的第二个参数来解组您的配置(请参阅viper.go - L904

为了简单起见,您可以这样做,根据我用您的示例复制的一个简单示例,可以在下面完成

package main

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

type ServerConfiguration struct {
    Port string `mapstructure:"server_port"`
}

type Configuration struct {
    Server ServerConfiguration `mapstructure:",squash"`
}

func main() {
    var result map[string]interface{}
    var config Configuration
    viper.SetConfigFile(".env")
    if err := viper.ReadInConfig(); err != nil {
        fmt.Printf("Error reading config file, %s", err)
    }

    err := viper.Unmarshal(&result)
    if err != nil {
        fmt.Printf("Unable to decode into map, %v", err)
    }

    decErr := mapstructure.Decode(result, &config)

    if decErr != nil {
        fmt.Println("error decoding")
    }

    fmt.Printf("config:%+v\n", config)
}
Run Code Online (Sandbox Code Playgroud)

您可以根据您的实际用例自定义此工作示例。有关嵌入式结构的映射结构标签的更多信息可以在此处squash找到