2017-04-14 17 views
1

我想將結構對象傳遞給函數&能夠從該函數訪問其指針值。我無法理解以下原因導致錯誤的原因。訪問函數內結構的指針值

func GetStructFieldPointers(u interface{}, jsonFields []string) []interface{} { 
    structVal := reflect.ValueOf(&u).Elem() 
    structType := reflect.TypeOf(u) 
    numberOfFields := structVal.NumField() // getting error here reflect: 
              // call of reflect.Value.NumField 
              // on interface Value 
    numberOfJSONFields := len(jsonFields) 
    res := make([]interface{}, numberOfJSONFields) 
    fmt.Println(jsonFields) 
    for fieldIndex, field := range jsonFields { 
     for i := 0; i < numberOfFields; i++ { 
      if structType.Field(i).Tag.Get("json") == field { 
       valueField := structVal.Field(i) 
       res[fieldIndex] = valueField.Addr().Interface() 
      } 
     } 
    } 

    return res 
} 

type User struct { 
    Id    int  `json:"id"` 
    Name   string `json:"name"` 
    Address  string `json:"address"` 
} 
user := User{} 
res := GetStructFieldPointers(user, []string{"id", "name"}) 

爲了使這項工作,我不得不做出structType作爲參數,像下面:

func GetStructFieldPointers(u interface{}, structType reflect.Type, jsonFields []string) []interface{} { 
    structVal := reflect.ValueOf(u).Elem() 
    // structType := reflect.TypeOf(u) 
    numberOfFields := structVal.NumField() 
    numberOfJSONFields := len(jsonFields) 
    res := make([]interface{}, numberOfJSONFields) 
    fmt.Println(jsonFields) 
    for fieldIndex, field := range jsonFields { 
     for i := 0; i < numberOfFields; i++ { 
      if structType.Field(i).Tag.Get("json") == field { 
       valueField := structVal.Field(i) 
       res[fieldIndex] = valueField.Addr().Interface() 
      } 
     } 
    } 

    return res 
} 

user := User{} 
res := GetStructFieldPointers(&user, reflect.TypeOf(user), []string{"id", "name"}) 

我想知道如何通過User{}作爲參數&使用兩個reflect.ValueOf &反映.TypeOf調用。

回答

3

在此行中:structVal := reflect.ValueOf(&u).Elem()你服用的接口(您FUNC的說法),而不是一個地址接口的潛在價值的地址,然後你傳遞指針ValueOf,所以.Elem()通話返回指針所指向的「元素值」,即interface,而不是結構。

如果你知道傳入的值是一個結構而不是一個指針,你只需要這個:structVal := reflect.ValueOf(u)

如果一個指針傳遞給你的func,例如GetStructFieldPointers(&u, ...那麼這就是你想要的:structVal := reflect.ValueOf(u).Elem()

但你也可以通過檢查值的種類來處理這兩種情況。

rv := reflect.ValueOf(u) 
if rv.Kind() == reflect.Ptr { 
    rv = rv.Elem() 
} 
if rv.Kind() == reflect.Struct { 
    fmt.Println(rv.NumField()) 
} 

https://play.golang.org/p/9F9LNnwEaH

更新: 你的代碼接過更好看......如果你希望能夠得到您的結構的字段的地址,您需要將指針傳遞到結構作爲參數,否則這些字段將無法尋址。

https://play.golang.org/p/RaA2rau3s-

+0

感謝您的回答。 – Sengkathir