2015-10-15 66 views
0

我有這樣反思匿名結構領域指針

type duration struct { 
    time.Duration 
} 

一個結構和另外一個類似的

type Config struct { 
    Announce duration 
} 

我使用反射來標誌分配給結構配置的領域。但是,對於類型爲duration的特定用例,我卡住了。 問題是,當我做一個開關類型,我得到*config.duration,而不是*time.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) { // 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) 
      } 
     } 
    } 
} 

感謝

回答

0

好了,一些挖掘後,並感謝我的IDE,我發現,使用的方法elem()ptr誰返回一個指針*time.Duration做的伎倆。如果我直接使用&ptr.Duration

以下是工作代碼。

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