1

我正在尝试理解 golang 接口,我的问题是为什么 err2.What 未定义。

这是一个简单的代码。输出表明 err 和 err2 与 *main.MyError 具有相同的类型,但 err2 没有字段“What”,因此 err 和 err2 之间肯定存在一些差异,但我无法在这里弄清楚差异。我刚开始学习golang不久,任何帮助将不胜感激。

package main

import (
        "fmt"
        "time"
        "reflect"
)

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() {
        err := &MyError{time.Now(), "Hello"}
        fmt.Println(reflect.TypeOf(err))
        fmt.Println(err.What)   

        err2 := run()
        fmt.Println(reflect.TypeOf(err2))
        fmt.Println(err2.What)
}

预期输出:

main.MyError
Hello
main.MyError
it didn't work

实际输出:

\# command-line-arguments ./test.go:34:18: err2.What undefined (type error has no field or method What)

4

2 回答 2

1

该函数run()返回一个 type 的值error,它是一个接口类型。是的,它包含一个具体类型的值*MyError,但是要访问MyError的字段,您需要使用类型断言

fmt.Println(err2.(*MyError).What)

在Go Playground上尝试一下。

请注意,error类型的值可能包含其他具体类型的值,实际上是实现error接口的任何类型。如果它包含另一个类型的值,上述类型断言将导致运行时恐慌。

如果你不确定是否err2真的持有一个类型的值*MyError并且你想避免运行时恐慌,你可以使用类型断言的特殊形式来获取这个信息,并且只有在这样的情况下才采取行动:

if myerror, ok := err2.(*MyError); ok {
    fmt.Println(myerror.What) // Here myerror has static type *MyError
} else {
    fmt.Println("Some other error:", err2)
}

在Go Playground上试试这个。

于 2019-07-15T07:45:09.100 回答
0

我认为错误类型的接口是让你Error()在具体结构中使用没有任何细节的方法。您可以在Go Playground上查看

于 2019-07-15T08:05:27.700 回答