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
答案 0 :(得分:13)
问题在于作为错误接口传递到通道的值不是nil
,而是指向nil的exec.Error
指针。
如果您更改以下程序,该程序将正常运行:
go func() {
var e *exec.Error = nil
if e == nil {
errChan <- nil
}
}()
这是解决问题的合适方法,因为报告没有发生错误的惯用方法是传递一个nil错误接口。
但是,如果你想改变main(可能是因为你使用了第三方软件包,这使得返回指针的错误设置为nil),你将不得不对特定类型做一个类型断言(* exec) .Error)然后检查它是否为nil,否则使用reflect包。
使用反射检查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
答案 1 :(得分:1)
使其工作的另一种方法是更改通道签名并明确说这是指向错误的通道指针而不是接口错误通道:
这有效:
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
这篇文章只是为了更深入地了解这个令人困惑的问题。 发生错误是发送错误的惯用方法。