Go 的介面有時會讓底層型別變得不明確。事實上,空介面可以接受任何具體值(包括基本型別)。型別斷言讓我們能用以下語法取出介面值底層的具體值:interfaceVariable.(concreteType)。
如果把這個敘述的結果指定給單一變數,就等於斷言這個介面變數存放的是該具體型別的值。因此,如果介面值不是指定的具體型別,在執行時就可能會 panic。例如:
var input interface{} = 12
str := input.(string) // panic at runtime since input is not a string!
我們可以利用型別斷言的兩個回傳值,來測試介面值存放的是不是某個具體型別:底層值,以及一個回報斷言是否成功的布林值。例如:
str, ok := input.(string) // no panic if input is not a string
如果input存放的是string,str就會是底層值,而ok會是 true。如果input存放的不是string,str就會是string型別的零值(也就是"",空字串),而ok會是 false。無論哪種情況都不會 panic。
這種慣用寫法很常見:
str, ok := input.(string)
if !ok {
str = "a default value"
}
一個型別 switch可以連續執行多個型別斷言。它的語法和型別斷言相同(interfaceVariable.(concreteType)),但不用特定的concreteType,而是使用關鍵字type。以下是一個範例:
var i interface{} = 12 // try: 12.3, true, int64(12), []int{}, map[string]int{}
switch v := i.(type) {
case int:
fmt.Printf("the integer %d\n", v)
case string:
fmt.Printf("the string %s\n", v)
default:
fmt.Printf("type, %T, not handled explicitly: %#v\n", v, v)
}