【问题标题】:Why golang custom error variable has multiple types为什么golang自定义错误变量有多种类型
【发布时间】:2019-06-16 14:28:06
【问题描述】:

如果我要定义自定义错误,我是一个新的 gopher,并且对变量类型感到非常困惑

    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的类型到底是什么?为什么“error”是一个接口,也可以作为返回类型?

非常感谢

【问题讨论】:

    标签: go types error-handling


    【解决方案1】:

    The Go Programming Language Specification

    Errors

    预先声明的类型错误定义为

    type error interface {
        Error() string
    }
    

    这是表示错误条件的常规接口, nil 值表示没有错误。

    Interface types

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


    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)。

    【讨论】:

      【解决方案2】:

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

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

      • 声明a := 5后,a的静态类型为int,这就是a的全部知识。
      • 您的代码中e 的静态类型是error(因为这是errorGen 返回的内容)。
      • 您可以像这样明确说明静态类型:var b uint16 = 9

      现在 Go 中有接口类型。 error 就是这样的接口类型,见彼得的回答。一些变量的静态类型为error;你的e 就是一个例子。现在,接口类型变量的全部目的是存储实现该接口的各种类型的值。所以一个不是 nil 的接口变量以某种方式“包含”另一个变量(实际上是一个值)。此包含值的类型可以是任何实现该接口的类型。包含值的类型是“动态类型”。 类型断言让您可以提取这种动态类型的值。

      【讨论】:

      • 为什么 e 的统计类型是 error 而不是 pointer 考虑到 errorGen 正在返回一个地址
      • 看看errorGen func errorGen() error它返回一个error。返回的类型是函数签名中的类型。函数体将 *myError 存储在错误中并返回该错误。函数的返回类型由函数签名确定。在return 之后写的任何内容对于静态返回类型都无关紧要(只要它可以编译)。
      猜你喜欢
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 2012-12-03
      相关资源
      最近更新 更多