我是 Go 新手,想知道如何以惯用的方式解决以下问题:
我正在使用 viper 将配置文件加载到程序中。我选择 toml 格式是因为我想要一个配置文件,它可以指定几种不同格式的所需输入:例如,Alpha 提供程序需要一个 apikey,而 Beta 提供程序需要用户名和密码。
[alpha]
apikey = "123"
domain = "example.com"
# [beta]
# username = ""
# password = ""
# domain = ""
type ProviderService interface {
PrintDomain()
}
type Provider struct {
Alpha `mapstructure:"alpha"`
Beta `mapstructure:"beta"`
}
type Alpha struct {
Apikey string `mapstructure:"apikey"`
Domain string `mapstructure:"domain"`
}
type Beta struct {
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Domain string `mapstructure:"domain"`
}
func main() {
provider := loadConfig()
fmt.Printf("%+v\n", provider)
// provider.DoAThing() # <==== Want to do this; currently results in "ambiguous selector provider.DoAThing"
}
func (a Alpha) DoAThing() {
fmt.Println("domain", a.Domain)
}
func (b Beta) DoAThing() {
fmt.Println("domain", b.Domain)
}
func loadConfig() (p Provider) {
viper.AddConfigPath("./")
viper.SetConfigName("config")
viper.SetConfigType("toml")
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %w \n", err))
}
err = viper.Unmarshal(&p)
if err != nil {
log.Fatal("unable to decode into struct", err)
}
return p
}
上面的代码导致{Alpha:{Apikey:123 Domain:example.com} Beta:{Username: Password: Domain:}}
空/未使用的结构仍然存在。
最终,我希望 ProviderService 接口与提供者无关,因此我可以简单地调用provider.PrintDomain()
而不是provider.Alpha.PrintDomain()
让代码中散布着 if/else 语句。我也对构建代码以实现这一结果的其他方式持开放态度。
提前致谢!