Golang空接口與類型斷言的實(shí)現(xiàn)
空接口
定義
空接口是特殊形式的接口類型,普通的接口都有方法,而空接口沒(méi)有定義任何方法口,也因此,我們可以說(shuō)所有類型都至少實(shí)現(xiàn)了空接口。
type test interface {
}每一個(gè)接口都包含兩個(gè)屬性,一個(gè)是值,一個(gè)是類型。
var i interface{}
fmt.Printf("類型:%T----值:%v\n", i, i) //類型:<nil>----值:<nil>
可見(jiàn)對(duì)于空接口來(lái)說(shuō),這兩者都是 nil
使用場(chǎng)景
第一,通常我們會(huì)直接使用 interface{} 作為類型聲明一個(gè)實(shí)例,而這個(gè)實(shí)例可以承載任意類型的值。
func main() {
var i interface{}
i = 100
fmt.Println(i) //100
i = "yif"
fmt.Println(i) //yif
i = 3.14
fmt.Println(i) //3.14
i = false
fmt.Println(i) //false
}
第二,如果想讓你的函數(shù)可以接收任意類型的值 ,也可以使用空接口。如下代碼都正常打印:
func main() {
i := 100
s := "yif"
f := 3.14
test(i)
test(s)
test(f)
}
func test(i interface{}) {
fmt.Println(i)
}
上面寫(xiě)法有點(diǎn)麻煩,可以使用可變參數(shù)的函數(shù)。如下:
func main() {
i := 100
s := "yif"
f := 3.14
test(i, s, f)
}
func test(res ...interface{}) {
fmt.Println(res) //res是切片
for k, v := range res {
fmt.Println(k, v)
}
}
結(jié)果:
D:\workspace\go\src\test>go run main.go
[100 yif 3.14]
0 100
1 yif
2 3.14
第三,你也定義一個(gè)可以接收任意類型的 array、slice、map、strcut,例如這邊定義一個(gè)切片
func main() {
sli := make([]interface{}, 4)
sli[0] = 100
sli[1] = "yif"
sli[2] = []int{1, 2, 3}
sli[3] = [...]int{5, 6, 7}
fmt.Println(sli)
for k, v := range sli {
fmt.Println(k, v)
}
}
結(jié)果:
D:\workspace\go\src\test>go run main.go
[100 yif [1 2 3] [5 6 7]]
0 100
1 yif
2 [1 2 3]
3 [5 6 7]
空接口幾個(gè)要注意的坑
**第一,**空接口可以承載任意值,但不代表任意類型就可以承接空接口類型的值
空接口類型可以保存任何值,也可以從空接口中取出原值。
但要是你把一個(gè)空接口類型的對(duì)象,再賦值給一個(gè)固定類型(比如 int, string等類型)的對(duì)象賦值,是會(huì)報(bào)錯(cuò)的。
var i interface{} = 100
var t int = i // cannot use i (type interface {}) as type int in assignment: need type assertion
但是你使用短變量聲明,是可以的:
var i interface{} = 100
t := i
fmt.Println(t) //100
因?yàn)榫幾g器會(huì)根據(jù)等號(hào)右邊的值來(lái)推導(dǎo)變量的類型完成初始化。
**第二:**當(dāng)空接口承載數(shù)組和切片后,該對(duì)象無(wú)法再進(jìn)行切片
sli := []int{1, 2, 3, 4}
var i interface{}
i = sli
fmt.Println(i[1:2]) //cannot slice i (type interface {})
類型斷言
類型斷言(Type Assertion)是一個(gè)使用在接口值上的操作,用于檢查接口類型變量所持有的值是否實(shí)現(xiàn)了期望的接口或者具體的類型
類型斷言,僅能對(duì)靜態(tài)類型為空接口(interface{})的對(duì)象進(jìn)行斷言,否則會(huì)拋出錯(cuò)誤
Go語(yǔ)言中類型斷言的兩種語(yǔ)法
在Go語(yǔ)言中類型斷言的第一種語(yǔ)法格式如下:
t := i.(T)
這個(gè)表達(dá)式可以斷言一個(gè)接口對(duì)象(i)里不是 nil,并且接口對(duì)象(i)存儲(chǔ)的值的類型是 T,如果斷言成功,就會(huì)返回值給 t,如果斷言失敗,就會(huì)觸發(fā) panic。
func main() {
var i interface{} = 100
t := i.(int)
fmt.Println(t) //100
fmt.Println("------------------------------------")
s := i.(string)
fmt.Println(s)
}
結(jié)果【執(zhí)行第二次斷言的時(shí)候失敗了,并且觸發(fā)了 panic】:
D:\workspace\go\src\test>go run main.go
100
------------------------------------
panic: interface conversion: interface {} is int, not stringgoroutine 1 [running]:
main.main()
D:/workspace/go/src/test/main.go:32 +0x10e
exit status 2
如果要斷言的接口值是 nil,那我們來(lái)看看也是不是也如預(yù)期一樣會(huì)觸發(fā)panic
var i interface{}
var _ = i.(interface{})
結(jié)果:
D:\workspace\go\src\test>go run main.go
panic: interface conversion: interface is nil, not interface {}goroutine 1 [running]:
main.main()
D:/workspace/go/src/test/main.go:27 +0x34
exit status 2
在Go語(yǔ)言中類型斷言的另一種語(yǔ)法格式如下:
t, ok:= i.(T)
和上面一樣,這個(gè)表達(dá)式也是可以斷言一個(gè)接口對(duì)象(i)里不是 nil,并且接口對(duì)象(i)存儲(chǔ)的值的類型是 T,如果斷言成功,就會(huì)返回其類型給 t,并且此時(shí) ok 的值 為 true,表示斷言成功。
如果接口值的類型,并不是我們所斷言的 T,就會(huì)斷言失敗,但和第一種表達(dá)式不同的事,這個(gè)不會(huì)觸發(fā) panic,而是將 ok 的值設(shè)為 false ,表示斷言失敗,此時(shí)t 為 T 的零值。
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)
}
結(jié)果【運(yùn)行后輸出如下,可以發(fā)現(xiàn)在執(zhí)行第二次斷言的時(shí)候,雖然失敗了,但并沒(méi)有觸發(fā)了 panic】:
D:\workspace\go\src\test>go run main.go
10-true
=====分隔線1=====
-false
=====分隔線2=====
<nil> - false
=====分隔線3=====
10-true
10-true
上面這段輸出,你要注意的是第二個(gè)斷言的輸出在-false 之前并不是有沒(méi)有輸出任何 t2 的值,而是由于斷言失敗,所以 t2 得到的是 string 的零值也是 "" ,它是零長(zhǎng)度的,所以你看不到其輸出。
類型斷言配合 switch 使用
如果需要區(qū)分多種類型,可以使用 type switch 斷言。
func main() {
test(100)
test("yif")
test(3.14)
var i interface{} //nil
test(i)
test(nil)
}
func test(i interface{}) {
switch r := i.(type) {
case int:
fmt.Println(r, "是int型")
case string:
fmt.Println(r, "是字符串")
case nil:
fmt.Println(r, "是nil")
default:
fmt.Println("沒(méi)有結(jié)果!")
}
}
結(jié)果:
D:\workspace\go\src\test>go run main.go
100 是int型
yif 是字符串
沒(méi)有結(jié)果!
<nil> 是nil
<nil> 是nil
到此這篇關(guān)于Golang空接口與類型斷言的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Golang空接口與類型斷言內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
多階段構(gòu)建優(yōu)化Go?程序Docker鏡像
這篇文章主要為大家介紹了多階段構(gòu)建優(yōu)化Go?程序Docker鏡像,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
在go文件服務(wù)器加入http.StripPrefix的用途介紹
這篇文章主要介紹了在go文件服務(wù)器加入http.StripPrefix的用途介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
實(shí)時(shí)通信的服務(wù)器推送機(jī)制 EventSource(SSE) 簡(jiǎn)介附go實(shí)現(xiàn)示例代碼
EventSource是一種非常有用的 API,適用于許多實(shí)時(shí)應(yīng)用場(chǎng)景,它提供了一種簡(jiǎn)單而可靠的方式來(lái)建立服務(wù)器推送連接,并實(shí)現(xiàn)實(shí)時(shí)更新和通知,這篇文章主要介紹了實(shí)時(shí)通信的服務(wù)器推送機(jī)制 EventSource(SSE)簡(jiǎn)介附go實(shí)現(xiàn)示例,需要的朋友可以參考下2024-03-03
go語(yǔ)言題解LeetCode1128等價(jià)多米諾骨牌對(duì)的數(shù)量
這篇文章主要為大家介紹了go語(yǔ)言題解LeetCode1128等價(jià)多米諾骨牌對(duì)的數(shù)量示例詳解,2022-12-12
如何通過(guò)Golang的container/list實(shí)現(xiàn)LRU緩存算法
文章介紹了Go語(yǔ)言中container/list包實(shí)現(xiàn)的雙向鏈表,并探討了如何使用鏈表實(shí)現(xiàn)LRU緩存,LRU緩存通過(guò)維護(hù)一個(gè)雙向鏈表來(lái)管理數(shù)據(jù),確保在插入和刪除操作時(shí)能夠以O(shè)(1)的平均時(shí)間復(fù)雜度運(yùn)行,提供了鏈表的操作和使用場(chǎng)景,并附帶了實(shí)現(xiàn)LRU緩存的代碼示例,感興趣的朋友一起看看吧2025-03-03
golang sql語(yǔ)句超時(shí)控制方案及原理
一般應(yīng)用程序在執(zhí)行一條sql語(yǔ)句時(shí),都會(huì)給這條sql設(shè)置一個(gè)超時(shí)時(shí)間,本文主要介紹了golang sql語(yǔ)句超時(shí)控制方案及原理,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12
golang實(shí)現(xiàn)并發(fā)控制的方法和技巧
golang 是一門(mén)支持并發(fā)的編程語(yǔ)言,它提供了 goroutine 和 channel 等強(qiáng)大的特性,讓我們可以輕松地創(chuàng)建和管理多個(gè)執(zhí)行單元,實(shí)現(xiàn)高效的任務(wù)處理,在本文中,我們將介紹一些 golang 的并發(fā)控制的方法和技巧,希望對(duì)你有所幫助2024-03-03
go語(yǔ)言中反射機(jī)制的三種使用場(chǎng)景
本文主要介紹了go語(yǔ)言中反射機(jī)制的三種使用場(chǎng)景,包括JSON解析、ORM框架和接口適配,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02
Go使用Protocol?Buffers在數(shù)據(jù)序列化的優(yōu)勢(shì)示例詳解
這篇文章主要為大家介紹了Go使用Protocol?Buffers在數(shù)據(jù)序列化的優(yōu)勢(shì)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
Go strconv包實(shí)現(xiàn)字符串和基本數(shù)據(jù)類型轉(zhuǎn)換的實(shí)例詳解
在Go語(yǔ)言(Golang)的編程實(shí)踐中,strconv包是一個(gè)非常重要的標(biāo)準(zhǔn)庫(kù),它提供了在基本數(shù)據(jù)類型(如整型、浮點(diǎn)型、布爾型)和字符串之間的轉(zhuǎn)換功能,本文給大家介紹了關(guān)于Go語(yǔ)言字符串轉(zhuǎn)換strconv,需要的朋友可以參考下2024-09-09

