GoLang错误/接口机制

GoLang错误/接口机制,go,Go,首先,我不太确定这个问题是与错误有关,还是与GoLang中的接口有关 我正在按照教程学习GoLang。本教程附带了这个问题 这是错误接口的基本演示。当我像这样修改代码时,我感到困惑: package main import ( "fmt" "time" ) type MyError struct { When time.Time What string } func (e *MyError) Error() string { return fmt.S

首先,我不太确定这个问题是与错误有关,还是与GoLang中的接口有关

我正在按照教程学习GoLang。本教程附带了这个问题

这是错误接口的基本演示。当我像这样修改代码时,我感到困惑:

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() *MyError {
    return &MyError{
        time.Now(), "it didn't work",
    }
}

func main() {
    if err := run(); err != nil {
        fmt.Println(err)
    }
    err1 := MyError{time.Now(), "it works again"}
    fmt.Println(err1)
    fmt.Println(err1.Error())
}
这段代码的输出是:

at 2015-04-06 15:00:07.1541719 +0800 CST, it didn't work
{2015-04-06 15:00:07.155172 +0800 CST it works again}
at 2015-04-06 15:00:07.155172 +0800 CST, it works again
让我困惑的是fmt将在什么条件下隐式调用MyError.Error()接口

据我所知,第一个和第二个fmt.Println()应该具有相同的变量类型:MyError。但是很明显,第一个调用涉及MyError类型的Error()的隐式调用,而第二个调用则没有

是什么机制造成了这种差异


感谢您研究这个初学者的问题

fmt.Println
使用反射首先检查变量的类型,如果类型实现了
Stringer
接口,则调用
String
方法。其次,如果类型实现了
Error
接口,它将调用
Error
方法。

您的代码将Error()实现绑定到指针*MyError

在代码中,您传递的是类型(确切地说是其副本),而不是指针

如果你改变

err1 := MyError{time.Now(), "it works again"}


它会像你期望的那样工作。

谢谢!我做了测试,是的。谢谢你的解释!还有一个问题,对于struct类型,GoLang有stringer的默认实现,如果我们实现一个错误接口,会不会混淆fmt.Println,不知道使用哪个接口?实际上是相反的
Error()string
在@DaveC之前使用(优先于)
string()Error
,这很有趣,对吗?如果您同时定义了
Error()string
,那么定义
string()string
就没有用了,至少不能在指向类型结构的指针上。。。
err1 := &MyError{time.Now(), "it works again"}