如何实现 GetStringValueByField(n interface{}, field_name string) string 函数?

huangapple go评论88阅读模式
英文:

How to implement GetStringValueByField(n interface{}, field_name string) string

问题

我正在尝试实现一种方法,通过给定的结构体和字段名作为字符串,从任意结构体字段中获取一个值作为字符串。

使用反射(reflect),总是会导致恐慌。

恐慌: reflect: 在接口值上调用 reflect.Value.FieldByName
goroutine 16 [运行中]

// 尝试实现 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)
    // 结构体
    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 ""
}

希望这可以帮助到你!

英文:

I am trying to implement a method to get a value from a arbitrary struct-field as a string given by the struct and the fieldname as a string.

With reflect it is always panicing.

> panic: reflect: call of reflect.Value.FieldByName on interface Value
> goroutine 16 [running]

// 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

得分: 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

英文:

Here's how to get a string field by name:

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

huangapple
  • 本文由 发表于 2014年10月16日 22:00:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/26406380.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定