如何使用Go的反射包(reflection pkg)来获取切片结构字段的类型?

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

How to use Go reflection pkg to get the type of a slice struct field?

问题

我正在尝试使用反射来构建一个例程,该例程将列出传入的任意结构体中所有字段的名称、类型和种类。以下是我目前的代码:

type StatusVal int
type Foo struct {
    Name string
    Age  int
}
type Bar struct {
    Status StatusVal
    FSlice []Foo
}

func ListFields(a interface{}) {
    v := reflect.ValueOf(a).Elem()
    for j := 0; j < v.NumField(); j++ {
        f := v.Field(j)
        n := v.Type().Field(j).Name
        t := f.Type().Name()
        fmt.Printf("Name: %s  Kind: %s  Type: %s\n", n, f.Kind(), t)
    }
}

func main() {
    var x Bar
    ListFields(&x)
}

输出结果如下:

Name: Status  Kind: int  Type: StatusVal
Name: FSlice  Kind: slice  Type: 

当字段是切片时,类型为空白。我尝试了几种方法来获取切片的数据类型,但所有尝试都导致恐慌...通常是这个错误:

reflect: call of reflect.Value.Elem on slice Value

需要对这段代码进行哪些更改,以便输出中包含所有字段(包括切片)的类型?

这是Playground链接:https://play.golang.org/p/zpfrYkwvlZ

英文:

I'm trying to use reflection to build a routine that will list the Name, Kind and Type of all fields in an arbitrary struct that gets passed in. Here is what I've got so far:

type StatusVal int
type Foo struct {
	Name string
	Age  int
}
type Bar struct {
	Status StatusVal
	FSlice []Foo
}

func ListFields(a interface{}) {
	v := reflect.ValueOf(a).Elem()
	for j := 0; j &lt; v.NumField(); j++ {
		f := v.Field(j)
		n := v.Type().Field(j).Name
		t := f.Type().Name()
		fmt.Printf(&quot;Name: %s  Kind: %s  Type: %s\n&quot;, n, f.Kind(), t)
	}
}

func main() {
	var x Bar
	ListFields(&amp;x)
}

The output is as follows:

Name: Status  Kind: int  Type: StatusVal
Name: FSlice  Kind: slice  Type: 

When the field is a slice, the type is blank. I tried several ways to get the slice's data type, but all attempts resulted in a panic... usually this one:

reflect: call of reflect.Value.Elem on slice Value

What changes need to be made to this code so that the type for all fields, including slices, will be listed in the output?

Here's the playground link: https://play.golang.org/p/zpfrYkwvlZ

答案1

得分: 9

_type literal_ 中给定的切片类型,例如 []Foo,是一个 未命名 类型,因此 Type.Name() 返回一个空字符串 &quot;&quot;

请改用 Type.String()

t := f.Type().String()

然后输出结果(在 Go Playground 上尝试一下):

Name: Status  Kind: int  Type: main.StatusVal
Name: FSlice  Kind: slice  Type: []main.Foo

查看相关问题以了解更多关于类型及其名称的信息:https://stackoverflow.com/questions/36310538/identify-non-builtin-types-using-reflect/37292523#37292523

英文:

A slice type given in a type literal like []Foo is an unnamed type, hence Type.Name() returns an empty string &quot;&quot;.

Use Type.String() instead:

t := f.Type().String()

And then the output (try it on the Go Playground):

Name: Status  Kind: int  Type: main.StatusVal
Name: FSlice  Kind: slice  Type: []main.Foo

See related question to know more about types and their names: https://stackoverflow.com/questions/36310538/identify-non-builtin-types-using-reflect/37292523#37292523

huangapple
  • 本文由 发表于 2017年2月17日 17:22:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/42294015.html
匿名

发表评论

匿名网友

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

确定