类型断言(Type Assertion)

是一个使用在接口值上的操作,用于检查接口类型变量所持有的值是否实现了期望的接口或具体的类型。

value, ok := x.(T)

x表示一个interface{},T表示具体类型/接口类型。

可以根据布尔值ok判断x是否属于T类型:

  • 如果T是具体某个类型,类型断言会检查x的动态类型是否等于具体类型T。如果检查成功,类型断言返回的结果是x的动态值,其类型是T。
  • 如果T是接口类型,类型断言会检查x的动态类型是否满足T。如果检查成功,x的动态值不会被提取,返回值是一个类型为T的接口值。
  • 无论T是什么类型,如果x是nil接口值,类型断言都会失败。
package main

import (
	"fmt"
)

func main() {

	var x interface{}
	x = "Hello"

	value, ok := x.(string)
	fmt.Println(value, ok)  // Hello true

	value1, ok1 := x.([]interface{})
	fmt.Println(value1, ok1)  // [] false

	value2, ok2 := x.(map[string]interface{})
	fmt.Println(value2, ok2)  // map[] false

	var y interface{}
	value3, ok3 := y.(int)
	fmt.Println(value3, ok3)  // 0 false

	y = 1
	value4 := y.(int)
	fmt.Println(value4)  // 1

	value5 := y.(string)  // 如果不接收第二个参数,断言失败会直接panic,若x为nil也会panic
	fmt.Println(value5)  // panic: interface conversion: interface {} is int, not string

}

类型断言可配合switch使用:

package main

import (
    "fmt"
)

func main() {
  v := "hello world"
	fmt.Println(getType(v))  // string
}

func getType(v interface{}) string {
	switch t := v.(type) {
	case int:
		return "int"
	case float64:
		return "float64"
	case string:
		return "string"
	//... etc
	default:
		_ = t
		return "unknown"
	}
}