简体   繁体   中英

Reflection anonymous struct field pointer

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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