Go 结构不能为nil,但这是正在编译的
我正在玩围棋游戏,找到以下代码:Go 结构不能为nil,但这是正在编译的,go,Go,我正在玩围棋游戏,找到以下代码: package main import ( "fmt" "time" ) type MyError struct { When time.Time What string } func (e *MyError) Error() string { return fmt.Sprintf("at %v, %s", e.When, e.What) } func run() error { retur
package main
import (
"fmt"
"time"
)
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run() error {
return &MyError{
time.Now(),
"it didn't work",
}
}
func main() {
if err := run(); err != nil {
fmt.Println(err)
}
}
所以在这里我可以看到*MyError
实现了error
接口。但是,如果我在error
func中删除&
,并返回MyError
,我将收到编译时错误:
prog.go:19:无法将MyError文本(类型MyError)用作返回参数中的类型错误:MyError未实现错误(错误方法具有指针接收器)
。好的,我可以理解这一点,这样我就可以使函数Error
像这样编译并成功运行:
func (e MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run() error {
return MyError{
time.Now(),
"it didn't work",
}
}
然后我在main
func中看到有一个检查err
是否为nil
,因此如果我理解正确,funcerror
在某些情况下完全可能返回nil
。因此,MyError
struct可以取nil
值。但是如果我试图编译这个:
import (
"fmt"
"time"
)
type MyError struct {
When time.Time
What string
}
func (e MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run() error {
return nil
return MyError{
time.Now(),
"it didn't work",
}
}
func main() {
var err2 MyError = nil
fmt.Println(err2)
if err := run(); err != nil {
fmt.Println(err)
}
}
go编译器说:prog.go:27:不能在赋值中使用nil作为MyError类型
[进程以非零状态退出]
为什么在大写字母中编译成功,而在本例中编译失败?
结构是否可能是
nil
(我想不是,但为什么run
func编译?在第一个示例中,*MyError
实现了错误
接口。如您所见,它是一个指针,指针可以有nil
值
var err *MyError
err == nil // true
var err *MyError = new(MyError)
err == nil // false
但在第二个示例中,是MyError
实现了error
接口,它不再是指针
var err MyError
err == MyError{} // true
&err == nil // false
err == nil // Compilation error
这次err
的地址可以是nil
,而不是变量本身
作为比较,考虑<代码> int >代码>类型:<代码> var i int <代码>。例如,您可以检查
i==0
,但是如果测试i==nil
,这将是一个错误,因为nil
不是一个整数(与之前的MyError
完全不同)。但是您仍然可以检查i
的地址是否为nil
:&i==nil
编辑 请注意,此函数将始终返回
nil
(执行在第一次返回后立即停止):
它编译是因为函数的原型告诉它必须返回一个错误
,实际上,nil
是一个有效的错误
,MyError{}
变量也是如此。但是试着把这个函数原型改成这个:
func run() MyError
您将看到编译失败,因为nil
不是MyError
变量,即使它是error
类型的有效值。nil接口与包含nil值的接口不同
在您的问题中,您已经看到一个接口(在您的例子中,内置错误接口)可以是nil,并且得出了一个错误的结论,即可以实现该接口的每种类型也可以是nil。我理解这一点,但请查看run
函数。它返回MyError,但也可以返回nil。啊哈,现在有意义了。谢谢。:)
func run() MyError