2014-10-16 111 views
1

我想實現一個方法來從任意結構字段中獲取值作爲由結構和字段名字符串給出的字符串。如何實現GetStringValueByField(n接口{},字段名稱字符串)字符串

隨着反思它總是恐慌。

恐慌:反映:reflect.Value.FieldByName對接口值調用 夠程16 [運行]

// attempt to implement GetStringValueByFieldName() 
package main 

import "fmt" 

import "reflect" 
import "strconv" 

func main() { 

    a:=Order{A:"asdf", B:123} 
    fmt.Println(a) 
    fmt.Println(Test1(a, "A")) 
    fmt.Println(Test1(a, "B")) 
} 

type Order struct { 
    A string 
    B int64 
} 
func Test1 (n interface{}, field_name string) string { 
    var x string 
    s := reflect.ValueOf(&n).Elem() 
    x, ok := s.FieldByName(field_name).Interface().(string) 
    if ok { 
     fmt.Println(ok) 
    } 
    return x 
} 

func GetStringValueByFieldName(n interface{}, field_name string) string { 
    ps := reflect.ValueOf(&n) 
    // struct 
    s := ps.Elem() 
    if s.Kind() == reflect.Struct { 
     f := s.FieldByName(field_name) 
     if f.IsValid() { 
     if f.CanSet() { 
       if f.Kind() == reflect.Int { 
        return strconv.FormatInt(f.Int(),10) 
       } 
       if f.Kind() == reflect.String { 
        return f.String() 
       } 
     } 
    } 
    } 
    return "" 
} 

回答

7

下面介紹如何通過名字來獲得一個字符串字段:

package main 

import (
    "fmt" 
    "reflect" 
) 

func main() { 

    a := Order{A: "asdf", B: 123} 
    fmt.Println(a) 
    fmt.Println(GetStringValueByFieldName(a, "A")) 
    fmt.Println(GetStringValueByFieldName(&a, "A")) 
    fmt.Println(GetStringValueByFieldName(a, "B")) 
    fmt.Println(GetStringValueByFieldName(0, "B")) 
    fmt.Println(GetStringValueByFieldName(a, "C")) 
} 

type Order struct { 
    A string 
    B int64 
} 

func GetStringValueByFieldName(n interface{}, field_name string) (string, bool) { 
    s := reflect.ValueOf(n) 
    if s.Kind() == reflect.Ptr { 
     s = s.Elem() 
    } 
    if s.Kind() != reflect.Struct { 
     return "", false 
    } 
    f := s.FieldByName(field_name) 
    if !f.IsValid() { 
     return "", false 
    } 
    switch f.Kind() { 
    case reflect.String: 
     return f.Interface().(string), true 
    case reflect.Int: 
     return strconv.FormatInt(f.Int(), 10), true 
    // add cases for more kinds as needed. 
    default: 
     return "", false 
     // or use fmt.Sprint(f.Interface()) 
    } 
} 

playground

+1

thx很多。作品完美。很想投你一票,但我需要15點聲望才能這樣做。 – somedude 2014-10-16 22:23:12