Go reflect. How to check whether reflect.Type is an error type?

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

Go reflect. How to check whether reflect.Type is an error type?

问题

我需要确定地检查一个 reflect.Type 是否是一个错误类型。

在 Go 的反射中,没有专门用于错误类型的 reflect kind。在检查类型错误时,通常采用正式/惯用的方式是什么?

以下是一个完整的示例代码:

  1. // 根据函数的每个返回类型返回默认值的映射
  2. // error => err=nil
  3. // bool => true
  4. // struct => new struct
  5. func getDefaultValue(originalFunction interface{}) map[int]reflect.Value {
  6. defaultValues := make(map[int]reflect.Value)
  7. typeOfFunc := reflect.ValueOf(originalFunction).Type()
  8. numOut := typeOfFunc.NumOut() // 函数返回值的数量
  9. for i := 0; i < numOut; i++ {
  10. typeOut := typeOfFunc.Out(i) // 第 i 个返回值的类型
  11. switch typeOut.Kind() {
  12. case reflect.Bool:
  13. defaultValues[i] = reflect.ValueOf(true)
  14. case reflect.Struct:
  15. defaultValues[i] = reflect.New(typeOut).Elem()
  16. // --> 如何确定 reflect.Type 是否是错误类型,使用 switch 或 if...
  17. // case reflect.error: // 不存在
  18. // var err error = nil
  19. // defaultValues[i] = reflect.ValueOf(&err).Elem()
  20. default:
  21. // var err error = nil
  22. // defaultValues[i] = reflect.ValueOf(&err).Elem()
  23. fmt.Println("未识别返回值类型,索引为", i)
  24. }
  25. fmt.Println("返回值类型,索引为", i, typeOut, "kind", typeOut.Kind(), "是否可赋值给 err", typeOut.AssignableTo(reflect.TypeOf(errors.New(""))))
  26. }
  27. return defaultValues
  28. }

你可以在 Go Playground 上运行这个示例代码。

英文:

I need to assuredly check whether a reflect.Type is an error.

There is no reflect kind for error. What is the formal/idiomatic manner to check for type error in go reflect?

Go Playground Full Example

  1. //return map of default values, based on each return type of a function
  2. // error =&gt; err=nil
  3. // bool =&gt; true
  4. // struct =&gt; new struct
  5. func getDefaultValue(originalFunction interface{}) map[int]reflect.Value {
  6. defaultValues := make(map[int]reflect.Value)
  7. typeOfFunc := reflect.ValueOf(originalFunction).Type()
  8. numOut := typeOfFunc.NumOut() //number of function returns
  9. for i := 0; i &lt; numOut; i++ {
  10. typeOut := typeOfFunc.Out(i) // type of return for index i
  11. switch typeOut.Kind() {
  12. case reflect.Bool:
  13. defaultValues[i] = reflect.ValueOf(true)
  14. case reflect.Struct:
  15. defaultValues[i] = reflect.New(typeOut()).Elem()
  16. // --&gt; How to identify reflect.Type error assuredly, using switch or if...
  17. //case reflect.error: //don&#39;t exists
  18. // var err error = nil
  19. // defaultValues[i] = reflect.ValueOf(&amp;err).Elem()
  20. default:
  21. //var err error = nil
  22. //defaultValues[i] = reflect.ValueOf(&amp;err).Elem()
  23. fmt.Println(&quot;type of return index &quot;, i, &quot; was not identified&quot;)
  24. }
  25. fmt.Println(&quot;type of return index &quot;, i, typeOut, &quot;kind&quot;, typeOut.Kind(), &quot;assign to err &quot;, typeOut.AssignableTo(reflect.TypeOf(errors.New(&quot;&quot;))))
  26. }
  27. return defaultValues
  28. }

答案1

得分: 21

在Go语言中,error并不是特殊的东西。error只是一个预声明的接口类型,因此它在反射中没有自己的Kind。可以尝试以下代码:

  1. errorInterface := reflect.TypeOf((*error)(nil)).Elem()
  2. ...
  3. case reflect.Interface:
  4. if typOute.Implements(errorInterface) // 它是一个错误
英文:

In Go error is not something special. error is just a predeclared interface type so it doesn't have its own Kind in reflect.
Try something along:

  1. errorInterface := reflect.TypeOf((*error)(nil)).Elem()
  2. ...
  3. case reflect.Interface:
  4. if typOute.Implements(errorInterface) // it&#39;s an error

答案2

得分: 1

创建一个反射类型的新值,并进行类型断言:

  1. ...
  2. default:
  3. typeOutValue := reflect.New(typeOut)
  4. if _, ok := typeOutValue.Interface().(*error); ok {
  5. defaultValues[i] = typeOutValue.Elem()
  6. } else {
  7. fmt.Println("未识别返回索引的类型", i)
  8. }
  9. }

或者根据其接口类型使用switch语句:

  1. ...
  2. default:
  3. typeOutValue := reflect.New(typeOut)
  4. switch typeOutValue.Interface().(type) {
  5. case *error:
  6. defaultValues[i] = typeOutValue.Elem()
  7. default:
  8. fmt.Println("未识别返回索引的类型", i)
  9. }

通过这种方式,您可以处理任何其他您可以(并且希望)特别关注的接口类型,使用更符合Go语言习惯的代码,并减少对reflect包的依赖(包括开销等)。

英文:

Create a new value of the reflected type and do a type assertion:

  1. ...
  2. default:
  3. typeOutValue := reflect.New(typeOut)
  4. if _, ok := typeOutValue.Interface().(*error); ok {
  5. defaultValues[i] = typeOutValue.Elem()
  6. } else {
  7. fmt.Println(&quot;type of return index &quot;, i, &quot; was not identified&quot;)
  8. }
  9. }

or switch on its interface type:

  1. ...
  2. default:
  3. typeOutValue := reflect.New(typeOut)
  4. switch typeOutValue.Interface().(type) {
  5. case *error:
  6. defaultValues[i] = typeOutValue.Elem()
  7. default:
  8. fmt.Println(&quot;type of return index &quot;, i, &quot; was not identified&quot;)
  9. }

This way you can handle also any other interface type that you can (and want to) be particular about, with a more idiomatic Go code and reduced reliance on (or, at least, calls into) the reflect package (overhead and all that).

答案3

得分: -1

你也可以直接使用类型的名称。

英文:

You could also just use the type's name.

huangapple
  • 本文由 发表于 2015年6月7日 07:16:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/30688514.html
匿名

发表评论

匿名网友

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

确定