我正在玩Go Playground并找到这段代码:
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
接口。但是,如果我删除&
func中的error
并返回MyError
,则会收到编译时错误:
prog.go:19: cannot use MyError literal (type MyError) as type error in return argument: MyError does not implement error (Error method has pointer receiver)
。好的,我可以理解,所以我可以像这样创建函数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: cannot use nil as type MyError in assignment
[process exited with non-zero status]
为什么在大写的情况下编译成功,在这种情况下编译失败?
结构可能是nil
(我猜不是,但是为什么run
func编译?)
答案 0 :(得分:9)
在第一个示例中,*MyError
实现了error
接口。如您所见,它是一个指针,指针可以具有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
(执行在第一个return
之后停止):
func run() error {
return nil
return MyError{
time.Now(),
"it didn't work",
}
}
它编译是因为函数的原型告诉它必须返回error
,事实上,nil
是有效的error
,因此是MyError{}
变量。但是尝试将这个函数原型改为这个:
func run() MyError
您将看到编译失败,因为nil
不是MyError
变量,即使它是error
类型的有效值。
答案 1 :(得分:2)
nil接口与包含nil值的接口不同。
在你的问题中,你已经看到一个接口(在你的情况下,内置错误接口)可以是nil,并得出一个错误的结论,即每个可以实现接口的类型也可以是nil。