英文:
GoLang Error/Interface Mechanism
问题
首先,我不太确定这个问题更与错误相关还是与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() *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()的隐式调用,而第二个调用没有。
是什么机制造成了这种差异?
感谢您解答这个初学者的问题!
英文:
Firstly, I am not quite sure if this problem is more relevant to error, or to interface in GoLang
I am catching up the GoLang by following the tutorial. The question came with this tutorial page
It is a basic demonstration of the error interface. When I change the code a bit like this, I got confused:
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())
}
The output of this piece of code is:
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
The thing confused me is under what condition the fmt will implicitly call MyError.Error() interface.
To my understanding, the first and second fmt.Println() should have the same variable type: MyError. But obviously the first call involved an implicit call of Error() of the MyError type, while the second did not.
What mechanism made this difference?
Thanks for looking into this beginner's question!
答案1
得分: 1
你的代码将Error()实现绑定到指针*MyError。
在你的代码中,你传递的是类型(确切地说是它的副本),而不是指针。
如果你将
err1 := MyError{time.Now(), "it works again"}
改为
err1 := &MyError{time.Now(), "it works again"}
它将按照你的期望工作。
英文:
Your code binds the Error() implementation to a pointer *MyError.
In your code you are passing the type (a copy thereof to be precise) rather than a pointer.
If you change
err1 := MyError{time.Now(), "it works again"}
to
err1 := &MyError{time.Now(), "it works again"}
it will work as you expect.
答案2
得分: 0
fmt.Println
使用反射首先检查变量的类型,如果该类型实现了 Stringer
接口,则调用 String
方法。其次,如果该类型实现了 Error
接口,则调用 Error
方法。
英文:
fmt.Println
uses reflection to firstly check the type of the variable and if the type implements the Stringer
interface then it calls the String
method. Secondly if the type implements the Error
interface it calls the Error
method.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论