我正在尝试使用反射在 Golang 中解析结构体字段指针。

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

I'm trying to parse a struct field pointers with reflection in Golang

问题

所以我想要在一个结构体中打印出名称(可以是嵌套的),所以我尝试使用递归方法来实现,但是我无法成功。我已经粘贴了下面的代码,并且我得到了以下错误信息:"panic: reflect: call of reflect.Value.NumField on zero Value"。当结构体是扁平层次结构时,我可以做到这一点,但是当它是嵌套的时候就失败了。任何帮助都将不胜感激。我还参考了这篇帖子"https://www.reddit.com/r/golang/comments/g254aa/parse_struct_field_pointers_with_reflection_in/"。另外,该结构体是从protobuf构建的,因此使用了Ptr。

  1. package main
  2. import (
  3. "fmt"
  4. "reflect"
  5. )
  6. func check(e error) {
  7. if e != nil {
  8. panic(e)
  9. }
  10. }
  11. func getFields(protoStructure interface{}) {
  12. val := reflect.ValueOf(protoStructure).Elem()
  13. // if val.Kind() == reflect.Ptr {
  14. // val = val.Elem()
  15. // }
  16. valNumFields := val.NumField()
  17. for i := 0; i < valNumFields; i++ {
  18. field := val.Field(i)
  19. fieldKind := field.Kind()
  20. varDescription := val.Type().Field(i).Tag.Get("description")
  21. // fieldKindStr := field.Kind().String()
  22. fieldName := val.Type().Field(i).Name
  23. // fieldTypeStr := field.Type().String()
  24. fmt.Println(fieldName, varDescription)
  25. if fieldKind == reflect.Ptr {
  26. rvAsserted := field
  27. getFields(rvAsserted.Interface())
  28. // fmt.Println(rvAsserted.Type().String())
  29. }
  30. }
  31. return
  32. }
  33. func main() {
  34. getFields(&DeviceEnv{})
  35. }
英文:

So i want to print the names in a struct(it can be nested), so i'm trying to use a recursive method to do the same but i'm failing to do so.Ive pasted the code below and i get the following error "panic: reflect: call of reflect.Value.NumField on zero Value". I'm able to do it when it's a flat hierarchy but failing when its nested.Any help is appreciated.Also i used this post "https://www.reddit.com/r/golang/comments/g254aa/parse_struct_field_pointers_with_reflection_in/" for reference. Also, the struct is built from protobuf hence the Ptr.

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. reflect &quot;reflect&quot;
  5. )
  6. func check(e error) {
  7. if e != nil {
  8. panic(e)
  9. }
  10. }
  11. func getFields(protoStructure interface{}) {
  12. val := reflect.ValueOf(protoStructure).Elem()
  13. // if val.Kind() == reflect.Ptr {
  14. // val = val.Elem()
  15. // }
  16. valNumFields := val.NumField()
  17. for i := 0; i &lt; valNumFields; i++ {
  18. field := val.Field(i)
  19. fieldKind := field.Kind()
  20. varDescription := val.Type().Field(i).Tag.Get(&quot;description&quot;)
  21. // fieldKindStr := field.Kind().String()
  22. fieldName := val.Type().Field(i).Name
  23. // fieldTypeStr := field.Type().String()
  24. fmt.Println(fieldName, varDescription)
  25. if fieldKind == reflect.Ptr {
  26. rvAsserted := field
  27. getFields(rvAsserted.Interface())
  28. // fmt.Println(rvAsserted.Type().String())
  29. }
  30. }
  31. return
  32. }
  33. func main() {
  34. getFields(&amp;DeviceEnv{})
  35. }

答案1

得分: 1

请注意,我是一个语言模型,我无法直接运行代码。以下是您提供的代码的翻译:

  1. // 使用 reflect.Type 作为参数编写一个函数。对指针和结构体字段进行递归操作。
  2. func getFields(t reflect.Type, prefix string) {
  3. switch t.Kind() {
  4. case reflect.Ptr:
  5. getFields(t.Elem(), prefix)
  6. case reflect.Struct:
  7. for i := 0; i < t.NumField(); i++ {
  8. sf := t.Field(i)
  9. fmt.Println(prefix, sf.Name)
  10. getFields(sf.Type, prefix+" ")
  11. }
  12. }
  13. }
  14. // 使用方法如下:
  15. getFields(reflect.TypeOf(&Example{}), "")

您可以在playground上运行它。

英文:

Write a function with reflect.Type as an argument. Recurse on pointers and struct fields.

  1. func getFields(t reflect.Type, prefix string) {
  2. switch t.Kind() {
  3. case reflect.Ptr:
  4. getFields(t.Elem(), prefix)
  5. case reflect.Struct:
  6. for i := 0; i &lt; t.NumField(); i++ {
  7. sf := t.Field(i)
  8. fmt.Println(prefix, sf.Name)
  9. getFields(sf.Type, prefix+&quot; &quot;)
  10. }
  11. }
  12. }

Use it like this:

  1. getFields(reflect.TypeOf(&amp;Example{}), &quot;&quot;)

Run it on the playground

huangapple
  • 本文由 发表于 2022年6月23日 00:33:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/72719070.html
匿名

发表评论

匿名网友

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

确定