英文:
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())
    }
}
英文:
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())
   }
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论