我解析了一堆标志,然后尝试将这些值分配给结构中的字段,但是我努力将解析后的标志值设置到结构中,因为我无法键入断言或投射它。
这是我所拥有的代码的片段。不必过多担心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
}
})
})
答案 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