使用 viper 从 envfile 中读取配置
Using viper to read config from envfile
我不太明白毒蛇的工作原理。
这是我的代码:
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
问题是 Unmarshal 不起作用
例如,当我使用 configuration.Server.Port 时,它是空的
spf13/viper predominantly uses mapstructure package to convert between one native Go type to another i.e. when un-marshaling. The package internally uses map[string]interface{}
type to store your config (see viper.go - L1327). After that depending on the config type (your case being env
), viper calls the right parsing package to store your config values. For envfile type, it uses subosito/gotenv to put in the above said map type (see viper.go - L1501)
问题的症结在于如何让 viper 将映射中的此配置解组为您选择的结构。这是 mapstructure 包的用武之地,用于将地图解组为您定义的嵌套结构。此时你有两个选择
- 将配置解组为
map[string]interface{}
类型,然后使用 mapstructure 放入适当的结构
- 使用DecodeHookFunc as a 2nd argument to your method to unmarshal your config (See 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
我不太明白毒蛇的工作原理。 这是我的代码:
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
问题是 Unmarshal 不起作用 例如,当我使用 configuration.Server.Port 时,它是空的
spf13/viper predominantly uses mapstructure package to convert between one native Go type to another i.e. when un-marshaling. The package internally uses map[string]interface{}
type to store your config (see viper.go - L1327). After that depending on the config type (your case being env
), viper calls the right parsing package to store your config values. For envfile type, it uses subosito/gotenv to put in the above said map type (see viper.go - L1501)
问题的症结在于如何让 viper 将映射中的此配置解组为您选择的结构。这是 mapstructure 包的用武之地,用于将地图解组为您定义的嵌套结构。此时你有两个选择
- 将配置解组为
map[string]interface{}
类型,然后使用 mapstructure 放入适当的结构
- 使用DecodeHookFunc as a 2nd argument to your method to unmarshal your config (See 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