【问题标题】:GoLang Error/Interface MechanismGoLang 错误/接口机制
【发布时间】:2015-06-10 14:14:50
【问题描述】:

首先,我不太确定这个问题是否与错误更相关,或者与 GoLang 中的接口更相关

我正在按照教程学习 GoLang。这个问题来自本教程page

是错误界面的基本演示。当我像这样更改代码时,我感到很困惑:

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() 的隐式调用,而第二个则没有。

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

感谢您调查这个初学者的问题!

【问题讨论】:

    标签: go


    【解决方案1】:

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

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

    如果你改变了

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

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

    它将按您的预期工作。

    【讨论】:

    • 谢谢!我测试过,是的。
    【解决方案2】:

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

    【讨论】:

    • 感谢您的解释!还有一个问题,对于struct类型,GoLang有默认的stringer实现,如果我们实现一个error接口,会不会混淆fmt.Println,不知道用哪个接口?
    • 其实恰恰相反。 Error() string 用于(优先于)String() error
    • @DaveC 这很有趣吧?就好像你同时定义了Error() string 一样,定义String() string 是没有用的,至少不在指向你的类型结构的指针上......
    猜你喜欢
    • 2022-12-13
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    • 2017-05-17
    • 2016-10-15
    • 1970-01-01
    • 2023-03-09
    相关资源
    最近更新 更多