31. 說說 Go 語言中的空接口

Hi,你們好,我是明哥。git

在本身學習 Golang 的這段時間裏,我寫了詳細的學習筆記放在個人我的微信公衆號 《Go編程時光》,對於 Go 語言,我也算是個初學者,所以寫的東西應該會比較適合剛接觸的同窗,若是你也是剛學習 Go 語言,不防關注一下,一塊兒學習,一塊兒成長。github

個人在線博客:http://golang.iswbm.com
個人 Github:github.com/iswbm/GolangCodingTimegolang


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)
}

第二,若是想讓你的函數能夠接收任意類型的值 ,也可使用空接口3d

接收一個任意類型的值 示例指針

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用法


相關文章
相關標籤/搜索