前言
类型断言 (type assertion)
基本用法

断言语句

一个类型断言语句检查它操作对象的动态类型是否和断言的类型匹配。

value, ok := x.(T)
xTvalueok
x == nil
xTok
value := x.(T)

断言类型种类

T

具体类型

TxTok = truevalueok = false 且 value = nilx
// 错误用法
// combile error: invalid type assertion: num.(int) (non-interface type int on left)
num := 10
if v, ok := num.(int); ok {
	fmt.Println(v)
}

// 正确用法
if v, ok := interface{}(num).(int); ok {
	fmt.Println(v) // out: 10
}

接口类型

TxTxTxT
var w io.Writer  // w 只能调用 Write 方法
w = os.Stdout
rw := w.(io.ReadWriter) // success: *os.File has both Read and Write
// rw 可以使用 Read 和 Write 方法
xT
type HelloInterface interface {
	Hello()
}

var w io.Writer = os.Stdout
hello := w.(HelloInterface) // panic: interface conversion: *os.File is not interfacetest.HelloInterface: missing method Hello

type switch

switchTtype
switch i := x.(type) {
case nil:
	printString("x is nil")                // type of i is type of x (interface{})
case int:
	printInt(i)                            // type of i is int
case float64:
	printFloat64(i)                        // type of i is float64
case func(int) float64:
	printFunction(i)                       // type of i is func(int) float64
case bool, string:
	printString("type is bool or string")  // type of i is type of x bool or string
default:
	printString("don't know the type")     // type of i is type of x (interface{})
}
基于断言识别错误类型

实际的开发过程中,通常会自定义一些扩展的错误类型来承载比原生 error 更复杂的信息,如:

type GError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

func (g GError) Error() string {
	return fmt.Sprintf("Code:%s, Message:%s", g.Code, g.Message)
}

func (g GError) GetCode() string {
	return g.Code
}

func (g GError) GetMessage() string {
	return g.Message
}

GError 类型实现了 error 接口,那么当我们接收到一个错误,可以用类型断言来识别是否是 GError,并且做出对应的处理。

func callapi() *rest.GError {
}

err := callapi()
if err != nil {
	if gErr, ok := err.(*rest.GError); ok {
		fmt.Println(gErr.Error())
	} else {
		fmt.Println("system error")
}