Go语言错误/接口机制

huangapple go评论82阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2015年4月6日 15:09:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/29466918.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定