1. 程式人生 > 程式設計 >Go 語言中的空介面(推薦)

Go 語言中的空介面(推薦)

在自己學習 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

總結

到此這篇關於Go 語言中的空介面的文章就介紹到這了,更多相關go 語言空介面內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!