我有几个配置结构,我想自动将其解析为可接受的命令行标志(以允许用户通过 CLI 覆盖它们)。鉴于结构可能会随着时间的推移而演变,并且其中一个结构是interface{},反射似乎是正确的方法。我只需要解析字符串、整数和 float64。我得到了以下工作:
func ReconGenerateFlags(in *ReconConfig, cmd *cobra.Command) {
for _, f := range reflect.VisibleFields(reflect.TypeOf(*in)) {
group_name := f.Name
v := reflect.ValueOf(in).Elem().FieldByName(f.Name).Elem() // Return the concrete substructures pointed to by "in"
sub_fields := reflect.VisibleFields(v.Type())
for _, sub_f := range sub_fields {
tag_name := sub_f.Name
sub_v := v.FieldByName(tag_name)
full_flag_name := strings.ToLower(group_name) + "." + strings.ToLower(tag_name)
switch s := sub_v.Type().String(); s {
case "string":
ptr := (*string)(unsafe.Pointer(sub_v.UnsafeAddr()))
cmd.Flags().StringVar(ptr, flag_name, "", "")
case "int":
ptr := (*int)(unsafe.Pointer(sub_v.UnsafeAddr()))
cmd.Flags().IntVar(ptr, flag_name, 0, "")
//case "float64":
// ptr := (*float64)(unsafe.Pointer(sub_v.UnsafeAddr()))
// cmd.Flags().Float64Var(ptr, flag_name, 0.0, "")
default:
fmt.Printf("unrecognized type in config setup: %s\n", s)
}
}
}
}
但是当我取消注释 float64 块时,我感到恐慌:
panic: reflect.Value.UnsafeAddr of unaddressable value
goroutine 1 [running]:
reflect.Value.UnsafeAddr(...)
/usr/local/go/src/reflect/value.go:2526
所以,我的具体问题是
“有没有办法使它适用于 float64s?”,
我稍微宽泛的问题是
“有没有更好的反射方法不需要不安全的指针转换?”
我更愿意完全尊重类型系统,但如何通过反射做到这一点并不明显。另一种选择似乎是代码生成,我想避免这种情况,但如果需要可以争论。
在此先感谢您的任何输入!
波斯汪
相关分类