package main
import (
"fmt"
"os/exec"
)
func main() {
errChan := make(chan error)
go func() {
var e *exec.Error = nil
errChan <- e
}()
err := <-errChan
if err != nil {
fmt.Printf("err != nil, but err = %v\n", err)
}
}
The output is weird: err != nil, but err = <nil>
Try it here: http://play.golang.org/p/_iyh0m7O1a
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With