A nil pointer is sent to chan, but a "non-nil" received

The problem lies in that the value passed into the channel as a error interface is not nil, but rather a exec.Error pointer which points to nil.

The program will behave correctly if you change:

go func() {
    var e *exec.Error = nil
    if e == nil {
        errChan <- nil
    }
}()

This is the appropriate way to solve the problem because the idiomatic way to report that no error occurred is by passing a nil error interface.

However, if you want to change the main instead (maybe because you use a third party package which makes the mistake of returning pointers set to nil), you will have to either do a type assertion to the specific type (*exec.Error) and then check if it is nil, or else use the reflect package.

Example using reflect to check for nil:

func IsNil(i interface{}) bool {
    // Check if it is an actual nil-value
    if i == nil {
        return true
    }

    v := reflect.ValueOf(i)
    switch v.Kind() {
        // Only the following kinds can be nil
        case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
        return v.IsNil()        
    }

    return false
}

Working example: http://play.golang.org/p/rpG1PVTwwM

You can find a discussion about it here: https://groups.google.com/forum/#!topic/golang-nuts/QzVDKv7p0Vs


Note: This post is just to have a bit more insight into a potentially confusing problem. Using a channel of type error is the idiomatic way to send errors.

Another way around this would be to change the channel signature and explicitly say that is a channel pointer to error instead of a channel of interface errors:

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    errChan := make(chan *exec.Error)
    go func() {
        var e *exec.Error = nil
        errChan <- e
    }()
    err := <-errChan
    if err != nil {
        fmt.Printf("err != nil, but err = %v\n", err)
    } else {
    fmt.Printf("err == nil\n")
    }
}

http://play.golang.org/p/l6Fq8O0wJw

Tags:

Null

Go