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

3

9

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  => 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() //number of function returns

    for i := 0; i < 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()

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

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

        }

        fmt.Println("type of return index ", i, typeOut, "kind", typeOut.Kind(), "assign to err ", typeOut.AssignableTo(reflect.TypeOf(errors.New(""))))
    }

    return defaultValues
}
Koenraad answered 6/6, 2015 at 23:16 Comment(0)
G
21

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's an error
Greengrocer answered 6/6, 2015 at 23:26 Comment(2)
@Greengrocer could you please explain what is happening inside TypeOf ((*error)(nil)) ?Stopgap
nil is a literal nil. sometype(nil) is a type conversion of nil to a nil sometype. (*error)(nil) produces a nil *error from which we can take the type via TypeOf. Going back to the error interface is done via Elem.Greengrocer
S
1

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("type of return index ", i, " was not identified")
    }
}

or switch on its interface type:

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

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

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).

Stowage answered 20/8, 2020 at 11:30 Comment(0)
B
-1

You could also just use the type's name.

Boeotian answered 14/8, 2016 at 10:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.