获取Go中空结构切片的字段

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

Get fields of empty struct slice in Go

问题

我有一个函数:

  1. func (r *render) foo(v interface{}) {
  2. val := reflect.ValueOf(v)
  3. fields := structs.Fields(val.Index(0).Interface())
  4. ...
  5. }

该函数接受一个结构体切片,并尝试获取v的字段,但是如果v为空,则"val.Index(0)"会导致程序崩溃。有没有更好的方法来解决这个问题?

英文:

I have a function

  1. func (r *render) foo(v interface{}) {
  2. val := reflect.ValueOf(v)
  3. fields := structs.Fields(val.Index(0).Interface())
  4. ...

Which takes a slice of structs and tries to get the fields of v,
however if v is empty then "val.Index(0)" crashes the program. Is there a better way to do this?

答案1

得分: 2

你需要首先检查是否有一个切片,然后检查是否有一个空切片,同时你可能也应该检查是否有一个结构体:(示例)

  1. val := reflect.ValueOf(v)
  2. if val.Kind() != reflect.Slice {
  3. fmt.Println("不是一个切片")
  4. return
  5. }
  6. if val.Len() == 0 {
  7. fmt.Println("空切片")
  8. return
  9. }
  10. if val.Index(0).Kind() != reflect.Struct {
  11. fmt.Println("不是一个结构体切片")
  12. return
  13. }
  14. fields := structs.Fields(val.Index(0).Interface())
  15. ...

如果你只想从结构体类型中获取字段,而不管切片是否为空,你可以使用切片类型的Elem方法来提取它(示例)

  1. // 获取切片的内部类型
  2. t := val.Type().Elem()
  3. if t.Kind() != reflect.Struct {
  4. fmt.Println("不是一个结构体")
  5. return
  6. }
  7. fmt.Println("类型:", t)
  8. for i := 0; i < t.NumField(); i++ {
  9. fmt.Println(t.Field(i).Name)
  10. }
英文:

You need to check first if you have a slice to begin with, then check if you have an empty slice, and you probably should check that you have a struct too while you're at it: (example)

  1. val := reflect.ValueOf(v)
  2. if val.Kind() != reflect.Slice {
  3. fmt.Println(&quot;not a slice&quot;)
  4. return
  5. }
  6. if val.Len() == 0 {
  7. fmt.Println(&quot;empty slice&quot;)
  8. return
  9. }
  10. if val.Index(0).Kind() != reflect.Struct {
  11. fmt.Println(&quot;not a slice of structs&quot;)
  12. return
  13. }
  14. fields := structs.Fields(val.Index(0).Interface())
  15. ...

If you only want the fields from a struct type, regardless of if the slice is empty, you can use the slice type's Elem method to extract it (example)

  1. // get the internal type of the slice
  2. t := val.Type().Elem()
  3. if t.Kind() != reflect.Struct {
  4. fmt.Println(&quot;not a struct&quot;)
  5. return
  6. }
  7. fmt.Println(&quot;Type:&quot;, t)
  8. for i := 0; i &lt; t.NumField(); i++ {
  9. fmt.Println(t.Field(i).Name)
  10. }

huangapple
  • 本文由 发表于 2015年8月11日 00:03:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/31924199.html
匿名

发表评论

匿名网友

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

确定