Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 结构不能为nil,但这是正在编译的_Go - Fatal编程技术网

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
,因此如果我理解正确,func
error
在某些情况下完全可能返回
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