为了账号安全,请及时绑定邮箱和手机立即绑定

有条件地将毒蛇配置(toml)解组为结构的惯用方法

有条件地将毒蛇配置(toml)解组为结构的惯用方法

Go
皈依舞 2022-10-31 15:52:14
我是 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"`                      }                                                                上面的代码导致{Alpha:{Apikey:123 Domain:example.com} Beta:{Username: Password: Domain:}}空/未使用的结构仍然存在。最终,我希望 ProviderService 接口与提供者无关,因此我可以简单地调用provider.PrintDomain()而不是provider.Alpha.PrintDomain()让代码中散布着 if/else 语句。我也对构建代码以实现这一结果的其他方式持开放态度。提前致谢!
查看完整描述

2 回答

?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

一种可能的方法是使用反射

func main() {
    provider := loadConfig()
    fmt.Printf("%+v\n", provider)
    v := reflect.ValueOf(provider)
    for i := 0; i < v.NumField(); i++ {
        field := v.Field(i)
        fmt.Println("domain:", field.FieldByName("Domain"))
    }}

它将打印 Alpha 或 Beta 结构的“域”字段。

去游乐场


查看完整回答
反对 回复 2022-10-31
?
繁华开满天机

TA贡献1816条经验 获得超4个赞

这就是我最终得到的结果,它允许我根据 toml 文件中指定的内容有条件地加载结构,并且仍然使用接口将其视为结构不可知论。


如果有人有任何关于将其重构为更惯用的技巧,请告诉我!


type ProviderService interface {

    DoAThing()

}


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()

    if provider == nil {

        log.Fatal("unable to parse config file")

    }


    provider.DoAThing()

}


func (a Alpha) DoAThing() {

    fmt.Println("domain", a.Domain)

}

func (b Beta) DoAThing() {

    fmt.Println("domain", b.Domain)

}


func loadConfig() ProviderService {

    viper.AddConfigPath("./")

    viper.SetConfigName("config")

    viper.SetConfigType("toml")


    err := viper.ReadInConfig()

    if err != nil {

        panic(fmt.Errorf("Fatal error config file: %w \n", err))

    }


    var a Alpha

    _ = viper.UnmarshalKey("alpha", &a)

    if a != (Alpha{}) {

        return a

    }


    var b Beta

    _ = viper.UnmarshalKey("beta", &b)

    if b != (Beta{}) {

        return b

    }


    return nil

}


查看完整回答
反对 回复 2022-10-31
  • 2 回答
  • 0 关注
  • 135 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号