简体   繁体   English

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

[英]Reflection struct field.Set with a Flag pointer value

I have a bunch of flags parsed, and I'm then trying to assign those values to fields in a struct, but I'm struggling to get a parsed flag value set into the struct because I can't type assert it or cast it.我解析了一堆标志,然后尝试将这些值分配给结构中的字段,但是我很难将解析的标志值设置到结构中,因为我无法键入断言或强制转换它.

Here is a snippet of the code I have.这是我拥有的代码片段。 It's not important to worry too much about the IterFields function, basically the third argument is called for each field in the struct...不必过多担心IterFields function,基本上结构中的每个字段都会调用第三个参数...

Note: there are comments in the code below which highlight the error(s).注意:下面的代码中有注释突出显示错误。

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

f.Value is an interface type flag.Value abstracting all kinds of flag values. f.Value是一个接口类型flag.Value抽象了各种标志值。 As your code indicates, it's not of type bool but some non-exported *flag.boolValue .正如您的代码所示,它不是bool类型,而是一些未导出的*flag.boolValue You shouldn't be concerned about its dynamic type.你不应该关心它的动态类型。

You may use the Value.String() method to get its value as a string , which will be either "false" or "true" for bool types, you may use simple comparison to obtain a bool from it like f.Value.String() == "true" .您可以使用Value.String()方法将其值作为string来获取,对于 bool 类型,这将是"false""true" ,您可以使用简单的比较来从中获取bool ,例如f.Value.String() == "true"

But a better approach would be: all flag.Value values originating from the flag package also implement flag.Getter which also has a Get() method that will directly return a bool value in case of a bool flag (wrapped in interface{} of course).但更好的方法是:所有来自flag package 的flag.Value值也实现flag.Getter ,它还有一个Get()方法,在 bool 标志的情况下将直接返回一个bool值(包装在interface{}课程)。 Just use that:只需使用它:

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

The above works for fields of any type (given that the flag's value type is assignable to the field's type).以上适用于任何类型的字段(假设标志的值类型可分配给字段的类型)。

For bool fields only, alternatively you may also use:仅对于bool字段,或者您也可以使用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM