英文:
Reflection anonymous struct field pointer
问题
我有一个类似这样的结构体:
type duration struct {
time.Duration
}
还有一个类似这样的结构体:
type Config struct {
Announce duration
}
我正在使用反射将标志分配给结构体Config的字段。然而,在类型为duration
的特定用例中,我遇到了问题。问题是,当我使用switch
语句判断类型时,我得到的是*config.duration
而不是*time.Duration
。我该如何访问匿名字段?
以下是完整的代码:
func assignFlags(v interface{}) {
// 将其解引用为可寻址的值
xv := reflect.ValueOf(v).Elem()
xt := xv.Type()
for i := 0; i < xt.NumField(); i++ {
f := xt.Field(i)
// 获取此字段的标签
name := f.Tag.Get("long")
short := f.Tag.Get("short")
usage := f.Tag.Get("usage")
addr := xv.Field(i).Addr().Interface()
// 将字段分配给标志
switch ptr := addr.(type) { // 在这里我得到的是`*config.duration`
case *time.Duration:
if len(short) > 0 {
// 注意这不是flag,而是pflag库。第一个参数的类型必须是`*time.Duration`
flag.DurationVarP(ptr, name, short, 0, usage)
} else {
flag.DurationVar(ptr, name, 0, usage)
}
}
}
}
希望对你有帮助!
英文:
I have a struct like this
type duration struct {
time.Duration
}
and another one like that
type Config struct {
Announce duration
}
I am using reflection to assign flags to the fields of the struct Config. However, with the particular use case of the type duration
, i am stuck.
The problem is that when i do a switch type, i got *config.duration
instead of *time.Duration
. How can i access the anonymous field ?
Here is the full code
func assignFlags(v interface{}) {
// Dereference into an adressable value
xv := reflect.ValueOf(v).Elem()
xt := xv.Type()
for i := 0; i < xt.NumField(); i++ {
f := xt.Field(i)
// Get tags for this field
name := f.Tag.Get("long")
short := f.Tag.Get("short")
usage := f.Tag.Get("usage")
addr := xv.Field(i).Addr().Interface()
// Assign field to a flag
switch ptr := addr.(type) { // i get `*config.duration` here
case *time.Duration:
if len(short) > 0 {
// note that this is not flag, but pflag library. The type of the first argument muste be `*time.Duration`
flag.DurationVarP(ptr, name, short, 0, usage)
} else {
flag.DurationVar(ptr, name, 0, usage)
}
}
}
}
Thanks
答案1
得分: 2
好的,以下是翻译好的内容:
好的,在进行一些调查后,借助我的IDE,我发现在ptr
上使用elem()
方法,它会返回一个指向*time.Duration
的指针,这样就可以解决问题。如果直接使用&ptr.Duration
也可以工作。
以下是可工作的代码:
func (d *duration) elem() *time.Duration {
return &d.Duration
}
func assignFlags(v interface{}) {
// 解引用为可寻址的值
xv := reflect.ValueOf(v).Elem()
xt := xv.Type()
for i := 0; i < xt.NumField(); i++ {
f := xt.Field(i)
// 获取该字段的标签
name := f.Tag.Get("long")
short := f.Tag.Get("short")
usage := f.Tag.Get("usage")
addr := xv.Field(i).Addr().Interface()
// 将字段分配给标志
switch ptr := addr.(type) {
case *duration:
if len(short) > 0 {
flag.DurationVarP(ptr.elem(), name, short, 0, usage)
} else {
flag.DurationVar(ptr.elem(), name, 0, usage)
}
}
}
}
希望对你有帮助!
英文:
Okay, after some digging, and thanks to my IDE, i found that using a method elem()
on ptr
who return a pointer *time.Duration
do the trick. It also work if i directly use &ptr.Duration
Here is the working code.
func (d *duration) elem() *time.Duration {
return &d.Duration
}
func assignFlags(v interface{}) {
// Dereference into an adressable value
xv := reflect.ValueOf(v).Elem()
xt := xv.Type()
for i := 0; i < xt.NumField(); i++ {
f := xt.Field(i)
// Get tags for this field
name := f.Tag.Get("long")
short := f.Tag.Get("short")
usage := f.Tag.Get("usage")
addr := xv.Field(i).Addr().Interface()
// Assign field to a flag
switch ptr := addr.(type) {
case *duration:
if len(short) > 0 {
flag.DurationVarP(ptr.elem(), name, short, 0, usage)
} else {
flag.DurationVar(ptr.elem(), name, 0, usage)
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论