在Go語言中,我們可以使用type switch語句查詢接口變量的真實數據類型,語法如下:
switch x.(type) { // cases }
x必須是接口類型。
來看一個詳細的示例:
type Stringer interface { String() string } var value interface{} // Value provided by caller. switch str := value.(type) { case string: return str //type of str is string case Stringer: //type of str is Stringer return str.String() }
語句switch中的value必須是接口類型,變量str的類型為轉換后的類型。
If the switch declares a variable in the expression, the variable will have the corresponding type in each clause. It's also idiomatic to reuse the name in such cases, in effect declaring a new variable with the same name but a different type in each case.
如果我們只關心一種類型該如何做?如果我們知道值為一個string,只是想將它抽取出來該如何做?只有一個case的類型switch是可以的,不過也可以用類型斷言(type assertions)。類型斷言接受一個接口值,從中抽取出顯式指定類型的值。其語法借鑒了類型switch子句,不過是使用了顯式的類型,而不是type關鍵字,如下:
x.(T)
同樣,x必須是接口類型。
str := value.(string)
上面的轉換有一個問題,如果該值不包含一個字符串,則程序會產生一個運行時錯誤。為了避免這個問題,可以使用“comma, ok”的習慣用法來安全地測試值是否為一個字符串:
str, ok := value.(string) if ok { fmt.Printf("string value is: %q\n", str) } else { fmt.Printf("value is not a string\n") }
如果類型斷言失敗,則str將依然存在,並且類型為字符串,不過其為零值,即一個空字符串。
我們可以使用類型斷言來實現type switch的中例子:
if str, ok := value.(string); ok { return str } else if str, ok := value.(Stringer); ok { return str.String() }
這種做法沒有多大實用價值。