Reputation: 8425
I have a function with interface argument:
func f(e error) {
if e == nil {
fmt.Println("YEY! NIL") // how to get here?
} else {
fmt.Println("NOT NIL :(")
}
}
How do I pass it a nil value via reflect
so that it passes == nil
check?
Approach 1:
func main() {
rf := reflect.ValueOf(f)
nilArg := reflect.Zero(reflect.TypeOf((error)(nil))) // panic: reflect: Zero(nil)
rf.Call([]reflect.Value{nilArg})
}
Approach 2:
type MyError struct{}
func (e MyError) Error() string {
return ""
}
func main() {
rf := reflect.ValueOf(f)
nilArg := reflect.Zero(reflect.TypeOf(&MyError{})) // NOT NIL :(
rf.Call([]reflect.Value{nilArg})
}
Second approach doesn't work due to https://golang.org/doc/faq#nil_error
Playground: https://play.golang.org/p/V0bMSPcCKI
Upvotes: 3
Views: 2668
Reputation: 120999
Use the expression reflect.TypeOf((*error)(nil)).Elem()
to get the reflect.Type for interface error
.
The first approach in the question does not work because the expression reflect.TypeOf((error)(nil))
returns nil
. The concrete type of a nil interface value is nil.
The trick is to pass a non-interface value to reflect.TypeOf()
and use reflect methods to get the desired reflect.Type
from there. In this answer, I pass a *error
to reflect.TypeOf()
and call Elem
on the result to get the reflect.Type
for error
.
Use the following to create nilArg
:
nilArg := reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
Upvotes: 6
Reputation: 5898
You have two options, basically e
in the arguments to function f
is (*MyError)(nil)
not nil
. So either assert the interface back to type MyError
or use more reflection to check if it's nil.
e.(*MyError) == nil
or
reflect.ValueOf(e).IsNil()
Runnable Example: https://play.golang.org/p/2KWguSx618
useful links:
Upvotes: 0