如何实现GetStringValueByField(n interface {},field_name string)字符串

时间:2014-10-16 14:00:04

标签: reflection go

我正在尝试实现一个方法,将任意struct-field中的值作为struct给出的字符串,将fieldname作为字符串。

通过反思,它总是在蠢蠢欲动。

  

恐慌:反映:在接口Value上调用reflect.Value.FieldByName   goroutine 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 ""
}

1 个答案:

答案 0 :(得分: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