Hi,大家好,我是明哥,
在自己學習 Golang 的這段時間里,我寫了詳細的學習筆記放在我的個人微信公眾號 《Go編程時光》,對于 Go 語言,我也算是個初學者,因此寫的東西應該會比較適合剛接觸的同學,如果你也是剛學習 Go 語言,不防關注一下,一起學習,一起成長,
我的在線博客:http://golang.iswbm.com
我的 Github:github.com/iswbm/GolangCodingTime
1. 什么是空介面?
空介面是特殊形式的介面型別,普通的介面都有方法,而空介面沒有定義任何方法口,也因此,我們可以說所有型別都至少實作了空介面,
type empty_iface interface {
}
每一個介面都包含兩個屬性,一個是值,一個是型別,
而對于空介面來說,這兩者都是 nil,可以使用 fmt 來驗證一下
package main
import (
"fmt"
)
func main() {
var i interface{}
fmt.Printf("type: %T, value: %v", i, i)
}
輸出如下
type: <nil>, value: <nil>
2. 如何使用空介面?
第一,通常我們會直接使用 interface{} 作為型別宣告一個實體,而這個實體可以承載任意型別的值,
package main
import (
"fmt"
)
func main() {
// 宣告一個空介面實體
var i interface{}
// 存 int 沒有問題
i = 1
fmt.Println(i)
// 存字串也沒有問題
i = "hello"
fmt.Println(i)
// 存布林值也沒有問題
i = false
fmt.Println(i)
}
第二,如果想讓你的函式可以接收任意型別的值 ,也可以使用空介面
接收一個任意型別的值 示例
package main
import (
"fmt"
)
func myfunc(iface interface{}){
fmt.Println(iface)
}
func main() {
a := 10
b := "hello"
c := true
myfunc(a)
myfunc(b)
myfunc(c)
}
接收任意個任意型別的值 示例
package main
import (
"fmt"
)
func myfunc(ifaces ...interface{}){
for _,iface := range ifaces{
fmt.Println(iface)
}
}
func main() {
a := 10
b := "hello"
c := true
myfunc(a, b, c)
}
第三,你也定義一個可以接收任意型別的 array、slice、map、strcut,例如這邊定義一個切片
package main
import "fmt"
func main() {
any := make([]interface{}, 5)
any[0] = 11
any[1] = "hello world"
any[2] = []int{11, 22, 33, 44}
for _, value := range any {
fmt.Println(value)
}
}
3. 空介面幾個要注意的坑
坑1:空介面可以承載任意值,但不代表任意型別就可以承接空介面型別的值
從實作的角度看,任何型別的值都滿足空介面,因此空介面型別可以保存任何值,也可以從空介面中取出原值,
但要是你把一個空介面型別的物件,再賦值給一個固定型別(比如 int, string等型別)的物件賦值,是會報錯的,
package main
func main() {
// 宣告a變數, 型別int, 初始值為1
var a int = 1
// 宣告i變數, 型別為interface{}, 初始值為a, 此時i的值變為1
var i interface{} = a
// 宣告b變數, 嘗試賦值i
var b int = i
}
這個報錯,它就好比可以放進行禮箱的東西,肯定能放到集裝箱里,但是反過來,能放到集裝箱的東西就不一定能放到行禮箱了,在 Go 里就直接禁止了這種反向操作,(宣告:底層原理肯定還另有其因,但對于新手來說,這樣解釋也許會容易理解一些,)
.\main.go:11:6: cannot use i (type interface {}) as type int in assignment: need type assertion
坑2::當空介面承載陣列和切片后,該物件無法再進行切片
package main
import "fmt"
func main() {
sli := []int{2, 3, 5, 7, 11, 13}
var i interface{}
i = sli
g := i[1:3]
fmt.Println(g)
}
執行會報錯,
.\main.go:11:8: cannot slice i (type interface {})
坑3:當你使用空介面來接收任意型別的引數時,它的靜態型別是 interface{},但動態型別(是 int,string 還是其他型別)我們并不知道,因此需要使用型別斷言,
package main
import (
"fmt"
)
func myfunc(i interface{}) {
switch i.(type) {
case int:
fmt.Println("引數的型別是 int")
case string:
fmt.Println("引數的型別是 string")
}
}
func main() {
a := 10
b := "hello"
myfunc(a)
myfunc(b)
}
輸出如下
引數的型別是 int
引數的型別是 string
系列導讀
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用法

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/5012.html
標籤:Go
