Hi,大家好,我是明哥。
在自己學習 Golang 的這段時間裡,我寫了詳細的學習筆記放在我的個人微信公衆号 《Go程式設計時光》,對于 Go 語言,我也算是個初學者,是以寫的東西應該會比較适合剛接觸的同學,如果你也是剛學習 Go 語言,不防關注一下,一起學習,一起成長。
我的線上部落格:http://golang.iswbm.com 我的 Github:github.com/iswbm/GolangCodingTime
Type Assertion
Type Assertion(中文名叫:類型斷言),通過它可以做到以下幾件事情
- 檢查
是否為 nili
- 檢查
存儲的值是否為某個類型i
具體的使用方式有兩種:
第一種:
t := i.(T)
這個表達式可以斷言一個接口對象(i)裡不是 nil,并且接口對象(i)存儲的值的類型是 T,如果斷言成功,就會傳回值給 t,如果斷言失敗,就會觸發 panic。
來寫段代碼試驗一下
package main
import "fmt"
func main() {
var i interface{} = 10
t1 := i.(int)
fmt.Println(t1)
fmt.Println("=====分隔線=====")
t2 := i.(string)
fmt.Println(t2)
}
運作後輸出如下,可以發現在執行第二次斷言的時候失敗了,并且觸發了 panic
10
=====分隔線=====
panic: interface conversion: interface {} is int, not string
goroutine 1 [running]:
main.main()
E:/GoPlayer/src/main.go:12 +0x10e
exit status 2
如果要斷言的接口值是 nil,那我們來看看也是不是也如預期一樣會觸發panic
package main
func main() {
var i interface{} // nil
var _ = i.(interface{})
}
輸出如下,确實是會 觸發 panic
panic: interface conversion: interface is nil, not interface {}
goroutine 1 [running]:
main.main()
E:/GoPlayer/src/main.go:5 +0x34
exit status 2
第二種
t, ok:= i.(T)
和上面一樣,這個表達式也是可以斷言一個接口對象(i)裡不是 nil,并且接口對象(i)存儲的值的類型是 T,如果斷言成功,就會傳回其類型給 t,并且此時 ok 的值 為 true,表示斷言成功。
如果接口值的類型,并不是我們所斷言的 T,就會斷言失敗,但和第一種表達式不同的事,這個不會觸發 panic,而是将 ok 的值設為 false ,表示斷言失敗,此時t 為 T 的零值。
稍微修改下上面的例子,如下
package main
import "fmt"
func main() {
var i interface{} = 10
t1, ok := i.(int)
fmt.Printf("%d-%t\n", t1, ok)
fmt.Println("=====分隔線1=====")
t2, ok := i.(string)
fmt.Printf("%s-%t\n", t2, ok)
fmt.Println("=====分隔線2=====")
var k interface{} // nil
t3, ok := k.(interface{})
fmt.Println(t3, "-", ok)
fmt.Println("=====分隔線3=====")
k = 10
t4, ok := k.(interface{})
fmt.Printf("%d-%t\n", t4, ok)
t5, ok := k.(int)
fmt.Printf("%d-%t\n", t5, ok)
}
運作後輸出如下,可以發現在執行第二次斷言的時候,雖然失敗了,但并沒有觸發了 panic。
10-true
=====分隔線1=====
-false
=====分隔線2=====
<nil> - false
=====分隔線3=====
10-true
10-true
上面這段輸出,你要注意的是第二個斷言的輸出在
-false
之前并不是有沒有輸出任何 t2 的值,而是由于斷言失敗,是以 t2 得到的是 string 的零值也是
""
,它是零長度的,是以你看不到其輸出。
Type Switch
如果需要區分多種類型,可以使用 type switch 斷言,這個将會比一個一個進行類型斷言更簡單、直接、高效。
package main
import "fmt"
func findType(i interface{}) {
switch x := i.(type) {
case int:
fmt.Println(x, "is int")
case string:
fmt.Println(x, "is string")
case nil:
fmt.Println(x, "is nil")
default:
fmt.Println(x, "not type matched")
}
}
func main() {
findType(10) // int
findType("hello") // string
var k interface{} // nil
findType(k)
findType(10.23) //float64
}
輸出如下
10 is int
hello is string
<nil> is nil
10.23 not type matched
額外說明一下:
- 如果你的值是 nil,那麼比對的是
case nil
- 如果你的值在 switch-case 裡并沒有比對對應的類型,那麼走的是 default 分支
參考文章
- Explain Type Assertions in Go
- Go interface 詳解 (四) :類型斷言
系列導讀
01. 開發環境的搭建(Goland & VS Code)
02. 學習五種變量建立的方法
03. 詳解資料類型:**整形與浮點型**
04. 詳解資料類型:byte、rune與string
05. 詳解資料類型:數組與切片
06. 詳解資料類型:字典與布爾類型
07. 詳解資料類型:指針
08. 面向對象程式設計:結構體與繼承
09. 一篇文章了解 Go 裡的函數
10. Go語言流程控制:if-else 條件語句
11. Go語言流程控制:switch-case 選擇語句
12. Go語言流程控制:for 循環語句
13. Go語言流程控制:goto 無條件跳轉
14. Go語言流程控制:defer 延遲調用
15. 面向對象程式設計:接口與多态
16. 關鍵字:make 和 new 的差別?
17. 一篇文章了解 Go 裡的語句塊與作用域
18. 學習 Go 協程:goroutine
19. 學習 Go 協程:詳解信道/通道
20. 幾個信道死鎖經典錯誤案例詳解
21. 學習 Go 協程:WaitGroup
22. 學習 Go 協程:互斥鎖和讀寫鎖
23. Go 裡的異常處理:panic 和 recover
24. 超詳細解讀 Go Modules 前世今生及入門使用
25. Go 語言中關于包導入必學的 8 個知識點
26. 如何開源自己寫的子產品給别人用?
27. 說說 Go 語言中的類型斷言?
28. 這五點帶你了解Go語言的select用法
