【问题标题】:Reflection struct field.Set with a Flag pointer value反射结构字段。使用标志指针值设置
【发布时间】:2020-08-11 14:26:42
【问题描述】:

我解析了一堆标志,然后我试图将这些值分配给结构中的字段,但我很难将解析的标志值设置到结构中,因为我无法键入断言它或投射它。

这是我拥有的代码的 sn-p。不用太担心IterFields函数,基本上结构中的每个字段都会调用第三个参数...

注意:下面的代码中有 cmets 会突出显示错误。

    flag.Parse()

    IterFields(st, v, func(field reflect.Value, sf reflect.StructField) {
        flag.VisitAll(func(f *flag.Flag) {
            if f.Name == strings.ToLower(sf.Name) || f.Name == sf.Tag.Get("short") {
                fmt.Printf("%+v, %T\n", f.Value, f.Value)
                // PRINTS: true, *flag.boolValue
                
                if v, ok := f.Value.(bool); ok {
                    fmt.Println("ok")
                } else {
                    fmt.Println("not ok")
                }
                // ERROR: impossible type assertion: bool does not implement flag.Value (missing Set method)
                
                field.Set(reflect.ValueOf(f.Value))
                // PANIC: value of type *flag.boolValue is not assignable to type bool
            }
        })
    })

【问题讨论】:

    标签: pointers go command-line-interface reflect


    【解决方案1】:

    f.Value 是一个接口类型flag.Value 抽象了各种标志值。正如您的代码所示,它不是bool 类型,而是一些未导出的*flag.boolValue。你不应该关心它的动态类型。

    您可以使用Value.String() 方法将其值作为string 获取,对于布尔类型,这将是"false""true",您可以使用简单的比较来从中获取bool f.Value.String() == "true".

    但更好的方法是:来自flag 包的所有flag.Value 值也实现flag.Getter,它还有一个Get() 方法,在布尔标志的情况下将直接返回bool 值(当然包含在interface{} 中)。只需使用它:

    field.Set(reflect.ValueOf(f.Value.(flag.Getter).Get()))
    

    以上适用于任何类型的字段(假设标志的值类型可分配给字段的类型)。

    仅限bool 字段,或者您也可以使用:

    field.SetBool(f.Value.(flag.Getter).Get().(bool))
    

    【讨论】:

      猜你喜欢
      • 2018-03-03
      • 1970-01-01
      • 1970-01-01
      • 2022-10-14
      • 1970-01-01
      • 2018-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多