我是新来的地鼠,如果我定义了自定义错误,我会被变量类型弄糊涂
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的确切类型是什么?以及为什么“错误”是一个接口并且还可以用作返回类型?
非常感谢
答案 0 :(得分:3)
您必须区分变量的“静态类型”和“动态类型”。
Go中的每个变量都具有完全一个静态类型。一些例子:
a := 5
的静态类型a
为int
之后,就可以知道a
了。e
的静态类型为error
(因为errorGen
返回的内容)。var b uint16 = 9
。现在Go中有接口类型。 error
是这样的接口类型,请参见Peter的答案。有些变量的静态类型为error
;您的e
是一个例子。现在,接口类型变量的全部目的是存储实现此接口的 variable 类型的值。因此,一个非零的接口变量会以某种方式“包含”另一个变量(实际上是一个值)。此包含的值的类型可以是实现接口的任何一种。包含值的类型是“动态类型”。
使用类型断言可以提取此动态类型的值。
答案 1 :(得分:1)
The Go Programming Language Specification
预定义的类型错误定义为
type error interface { Error() string }
它是表示错误情况的常规界面, nil值表示没有错误。
接口类型指定一个称为其接口的方法集。一种 接口类型的变量可以使用方法存储任何类型的值 设置为接口的任何超集。据说这种类型 实现该接口。
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
}
两种类型的断言都是正确的(ok
是true
)。