为什么Golang自定义错误变量具有多种类型

时间:2019-01-23 03:52:02

标签: go types error-handling

我是新来的地鼠,如果我定义了自定义错误,我会被变量类型弄糊涂

    import (
        "fmt"
        "reflect"
    )

    // custom errors
    type myError struct {
        msg string
    }

    func (m *myError) Error() string {
        return m.msg
    }

    func errorGen() error {
        return &myError{"custom error"}
    }

生成新错误并检查错误类型

    func main() {
        e := errorGen()
        fmt.Println(reflect.TypeOf(e).Kind()) // type = pointer

        // first type assertion
        _, ok := e.(error)
        if ok {
            fmt.Println("type assertion error") // type = error
        }

        // second type assertion
        _, ok = e.(*myError)
        if ok {
            fmt.Println("type assertion *myError") // type = pointer
        }
    }

因此在上面的代码变量'e'中同时显示2种类型。 e的确切类型是什么?以及为什么“错误”是一个接口并且还可以用作返回类型?

非常感谢

2 个答案:

答案 0 :(得分:3)

您必须区分变量的“静态类型”和“动态类型”。

Go中的每个变量都具有完全一个静态类型。一些例子:

  • 在声明a := 5的静态类型aint之后,就可以知道a了。
  • 您的代码中e的静态类型为error(因为errorGen返回的内容)。
  • 您可以像这样明确地声明静态类型:var b uint16 = 9

现在Go中有接口类型。 error是这样的接口类型,请参见Peter的答案。有些变量的静态类型为error;您的e是一个例子。现在,接口类型变量的全部目的是存储实现此接口的 variable 类型的值。因此,一个非零的接口变量会以某种方式“包含”另一个变量(实际上是一个值)。此包含的值的类型可以是实现接口的任何一种。包含值的类型是“动态类型”。 使用类型断言可以提取此动态类型的值。

答案 1 :(得分:1)

  

The Go Programming Language Specification

     

Errors

     

预定义的类型错误定义为

type error interface {
    Error() string
}
     

它是表示错误情况的常规界面,   nil值表示没有错误。

     

Interface types

     

接口类型指定一个称为其接口的方法集。一种   接口类型的变量可以使用方法存储任何类型的值   设置为接口的任何超集。据说这种类型   实现该接口。


e实现了预先声明的接口类型error

    // first type assertion
    _, ok := e.(error)
    if ok {
        fmt.Println("type assertion error") // type = error
    }

e的具体类型是指向类型myError的指针。

    // second type assertion
    _, ok = e.(*myError)
    if ok {
        fmt.Println("type assertion *myError") // type = pointer
    }

两种类型的断言都是正确的(oktrue)。