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

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

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

问题

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

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

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

// 根据函数的每个返回类型返回默认值的映射
// error  => err=nil
// bool   => true
// struct => new struct
func getDefaultValue(originalFunction interface{}) map[int]reflect.Value {
    defaultValues := make(map[int]reflect.Value)

    typeOfFunc := reflect.ValueOf(originalFunction).Type()

    numOut := typeOfFunc.NumOut() // 函数返回值的数量

    for i := 0; i < numOut; i++ {
        typeOut := typeOfFunc.Out(i) // 第 i 个返回值的类型
        switch typeOut.Kind() {
        case reflect.Bool:
            defaultValues[i] = reflect.ValueOf(true)
        case reflect.Struct:
            defaultValues[i] = reflect.New(typeOut).Elem()
        // --> 如何确定 reflect.Type 是否是错误类型,使用 switch 或 if...
        // case reflect.error: // 不存在
        //     var err error = nil
        //     defaultValues[i] = reflect.ValueOf(&err).Elem()
        default:
            // var err error = nil
            // defaultValues[i] = reflect.ValueOf(&err).Elem()
            fmt.Println("未识别返回值类型,索引为", i)
        }

        fmt.Println("返回值类型,索引为", i, typeOut, "kind", typeOut.Kind(), "是否可赋值给 err", typeOut.AssignableTo(reflect.TypeOf(errors.New(""))))
    }

    return defaultValues
}

你可以在 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

//return map of default values, based on each return type of a function
// error  =&gt; err=nil
// bool   =&gt; true
// struct =&gt; new struct
func getDefaultValue(originalFunction interface{}) map[int]reflect.Value {
    defaultValues := make(map[int]reflect.Value)

    typeOfFunc := reflect.ValueOf(originalFunction).Type()

    numOut := typeOfFunc.NumOut() //number of function returns

    for i := 0; i &lt; numOut; i++ {

	    typeOut := typeOfFunc.Out(i) // type of return for index i
	    switch typeOut.Kind() {

	    case reflect.Bool:
		    defaultValues[i] = reflect.ValueOf(true)

	    case reflect.Struct:
		    defaultValues[i] = reflect.New(typeOut()).Elem()

	    // --&gt; How to identify reflect.Type error assuredly, using switch or if...
	    //case reflect.error: //don&#39;t exists
	    //	var err error = nil
	    //	defaultValues[i] = reflect.ValueOf(&amp;err).Elem()

	    default:
		    //var err error = nil
		    //defaultValues[i] = reflect.ValueOf(&amp;err).Elem()
		    fmt.Println(&quot;type of return index &quot;, i, &quot; was not identified&quot;)

	    }

	    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;))))
    }

    return defaultValues
}

答案1

得分: 21

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

errorInterface := reflect.TypeOf((*error)(nil)).Elem()
...
case reflect.Interface:
    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:

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

答案2

得分: 1

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

...
default:
	typeOutValue := reflect.New(typeOut)

	if _, ok := typeOutValue.Interface().(*error); ok {
		defaultValues[i] = typeOutValue.Elem()
	} else {
		fmt.Println("未识别返回索引的类型", i)
	}
}

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

...
default:
	typeOutValue := reflect.New(typeOut)

	switch typeOutValue.Interface().(type) {
	case *error:
		defaultValues[i] = typeOutValue.Elem()
	default:
		fmt.Println("未识别返回索引的类型", i)
	}

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

英文:

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

...
default:
	typeOutValue := reflect.New(typeOut)

	if _, ok := typeOutValue.Interface().(*error); ok {
		defaultValues[i] = typeOutValue.Elem()
	} else {
		fmt.Println(&quot;type of return index &quot;, i, &quot; was not identified&quot;)
	}
}

or switch on its interface type:

...
default:
	typeOutValue := reflect.New(typeOut)

	switch typeOutValue.Interface().(type) {
	case *error:
		defaultValues[i] = typeOutValue.Elem()
	default:
		fmt.Println(&quot;type of return index &quot;, i, &quot; was not identified&quot;)
	}

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:

确定