问题描述
我不太了解毒蛇的工作原理。 这是我的代码:
configuration.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
}
.env
SERVER_PORT=:4747
问题是解组不起作用 例如,当我使用configuration.Server.Port时,它是空的
解决方法
spf13/viper主要使用mapstructure包在一种本机Go类型与另一种本机Go类型之间进行转换,即在取消编组时。软件包内部使用map[string]interface{}
类型存储您的配置(请参见viper.go - L1327)。之后,根据配置类型(您的情况为env
),vi蛇会调用正确的解析包来存储您的配置值。对于envfile类型,它使用subosito/gotenv来放入上述映射类型(请参见viper.go - L1501)
问题的症结在于如何使毒蛇在映射到您选择的结构的地图中解组此配置。这就是mapstructure软件包的出现位置,可将地图解组为您定义的嵌套结构。此时,您剩下两个选择
- 将配置解编为
map[string]interface{}
类型,然后使用mapstructure放入适当的结构 - 使用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)
}
您可以根据实际用例定制此工作示例。有关嵌入结构的mapstructure squash
标签的更多信息,请参见here