10
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)
    }
}

输出很奇怪:err != nil, but err = <nil> 在这里试试:http ://play.golang.org/p/_iyh0m7O1a

4

2 回答 2

15

问题在于作为错误接口传入通道的值不是nil,而是exec.Error指向 nil 的指针。

如果您更改,程序将正常运行:

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

这是解决问题的合适方法,因为报告未发生错误的惯用方法是传递一个 nil 错误接口。

但是,如果您想更改 main 代替(可能是因为您使用了第三方包,该包导致返回指针设置为 nil 的错误),您将不得不对特定类型进行类型断言 (*exec.Error)然后检查它是否为零,否则使用反射包。

使用反射检查 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
}

工作示例:http ://play.golang.org/p/rpG1PVTwwM

你可以在这里找到关于它的讨论:https ://groups.google.com/forum/#!topic/golang-nuts/QzVDKv7p0Vs

于 2013-10-11T11:36:02.020 回答
2

注意:这篇文章只是为了更深入地了解一个可能令人困惑的问题。 使用类型的通道 error 是发送错误的惯用方式。

解决此问题的另一种方法是更改​​通道签名并明确地说这是指向错误的通道指针,而不是接口错误的通道:

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

于 2013-10-11T19:15:41.883 回答