反射结构字段,用标志指针值设置

时间:2020-08-11 14:26:42

标签: pointers go command-line-interface reflect

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

这是我所拥有的代码的片段。不必过多担心IterFields函数,基本上是为结构体中的每个字段调用第三个参数...

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

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

1 个答案:

答案 0 :(得分:1)

f.Value是抽象所有标志值的接口类型flag.Value。如您的代码所示,它不是bool类型,而是一些未导出的*flag.boolValue。您不必担心它的动态类型。

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

但是更好的方法是:来自flag.Value包的所有flag值也实现flag.Getter,该值也具有Get()方法,该方法将直接返回{{如果是bool标志,则为1}}的值(当然用bool包装)。只需使用它即可:

interface{}

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

仅对于field.Set(reflect.ValueOf(f.Value.(flag.Getter).Get())) 字段,或者,您也可以使用:

bool