3

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

Grozz
  • 8,317
  • 4
  • 38
  • 53

2 Answers2

6

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

playground example

Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242
0

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:

Community
  • 1
  • 1
Zak
  • 5,515
  • 21
  • 33
  • valuable info, however the question is about passing the `nil` argument, not changing the check inside the function – Grozz May 12 '17 at 12:58
  • Thanks for the clarification, glad you found your answer! – Zak May 12 '17 at 13:45