Go 語(yǔ)言中關(guān)于接口的三個(gè)
我的在線博客:http://golang.iswbm.com
我的 Github:github.com/iswbm/GolangCodingTime
1. 對(duì)方法的調(diào)用限制
接口是一組固定的方法集,由于靜態(tài)類型的限制,接口變量有時(shí)僅能調(diào)用其中特定的一些方法。
請(qǐng)看下面這段代碼
package main import "fmt" type Phone interface { call() } type iPhone struct { name string } func (phone iPhone)call() { fmt.Println("Hello, iPhone.") } func (phone iPhone)send_wechat() { fmt.Println("Hello, Wechat.") } func main() { var phone Phone phone = iPhone{name:"ming's iphone"} phone.call() phone.send_wechat() }
我定義了一個(gè) Phone 的接口,只要求實(shí)現(xiàn) call 方法即可,也就是只要能打電話的設(shè)備就是一個(gè)電話(好像是一句沒用的廢話)。
然后再定義了一個(gè) iPhone 的結(jié)構(gòu)體,該結(jié)構(gòu)體接收兩個(gè)方法,一個(gè)是打電話( call 函數(shù)),一個(gè)是發(fā)微信(send_wechat 函數(shù))。
最后一步是關(guān)鍵,我們定義了一個(gè) Phone 接口類型的 phone 對(duì)象,該對(duì)象的內(nèi)容是 iPhone 結(jié)構(gòu)體。然后我們調(diào)用該對(duì)象的 call 方法,一切正常。
但是當(dāng)你調(diào)用 phone.send_wechat
方法,程序會(huì)報(bào)錯(cuò),提示我們 Phone 類型的方法沒有 send_wechat 的字段或方法。
# command-line-arguments ./demo.go:30:10: phone.send_wechat undefined (type Phone has no field or method send_wechat)
原因也很明顯,因?yàn)槲覀兊膒hone對(duì)象顯示聲明為 Phone 接口類型,因此 phone調(diào)用的方法會(huì)受到此接口的限制。
那么如何讓 phone 可以調(diào)用 send_wechat 方法呢?
答案是可以不顯示的聲明為 Phone接口類型 ,但要清楚 phone 對(duì)象實(shí)際上是隱式的實(shí)現(xiàn)了 Phone 接口,如此一來(lái),方法的調(diào)用就不會(huì)受到接口類型的約束。
修改 main 方法成如下
func main() { phone := iPhone{name:"ming's iphone"} phone.call() phone.send_wechat() }
運(yùn)行后,一切正常,沒有報(bào)錯(cuò)。
Hello, iPhone.
Hello, Wechat.
2. 調(diào)用函數(shù)時(shí)的隱式轉(zhuǎn)換
Go 語(yǔ)言中的函數(shù)調(diào)用都是值傳遞的,變量會(huì)在方法調(diào)用前進(jìn)行類型轉(zhuǎn)換。
比如下面這段代碼
import ( "fmt" ) func printType(i interface{}) { switch i.(type) { case int: fmt.Println("參數(shù)的類型是 int") case string: fmt.Println("參數(shù)的類型是 string") } } func main() { a := 10 printType(a) }
如果你運(yùn)行后,會(huì)發(fā)現(xiàn)一切都很正常
參數(shù)的類型是 int
但是如果你把函數(shù)內(nèi)的內(nèi)容搬到到外面來(lái)
package main import "fmt" func main() { a := 10 switch a.(type) { case int: fmt.Println("參數(shù)的類型是 int") case string: fmt.Println("參數(shù)的類型是 string") } }
就會(huì)有意想不到的結(jié)果,居然報(bào)錯(cuò)了。
# command-line-arguments ./demo.go:9:5: cannot type switch on non-interface value a (type int)
這個(gè)操作會(huì)讓一個(gè)新人摸不著頭腦,代碼邏輯都是一樣的,為什么一個(gè)不會(huì)報(bào)錯(cuò),一個(gè)會(huì)報(bào)錯(cuò)呢?
原因其實(shí)很簡(jiǎn)單。
當(dāng)一個(gè)函數(shù)接口 interface{} 空接口類型時(shí),我們說它可以接收什么任意類型的參數(shù)(江湖上稱之為無(wú)招勝有招)。
當(dāng)你使用這種寫法時(shí),Go 會(huì)默默地為我們做一件事,就是把傳入函數(shù)的參數(shù)值(注意:Go 語(yǔ)言中的函數(shù)調(diào)用都是值傳遞的)的類型隱式的轉(zhuǎn)換成 interface{} 類型。
如何進(jìn)行接口類型的顯示轉(zhuǎn)換
上面了解了函數(shù)中 接口類型的隱式轉(zhuǎn)換后,你的心里可能開始有了疑問了,難道我使用類型斷言,只能通過一個(gè)接收空接口類型的函數(shù)才能實(shí)現(xiàn)嗎?
答案當(dāng)然是 No.
如果你想手動(dòng)對(duì)其進(jìn)行類型轉(zhuǎn)換,可以像下面這樣子,就可以將變量 a 的靜態(tài)類型轉(zhuǎn)換為 interface{} 類型然后賦值給 b (此時(shí) a 的靜態(tài)類型還是 int,而 b 的靜態(tài)類型為 interface{})
var a int = 25 b := interface{}(a)
知道了方法后,將代碼修改成如下:
package main import "fmt" func main() { a := 10 switch interface{}(a).(type) { case int: fmt.Println("參數(shù)的類型是 int") case string: fmt.Println("參數(shù)的類型是 string") } }
運(yùn)行后,一切正常。
參數(shù)的類型是 int
3. 類型斷言中的隱式轉(zhuǎn)換
上面我們知道了,只有靜態(tài)類型為接口類型的對(duì)象才可以進(jìn)行類型斷言。
而當(dāng)類型斷言完成后,會(huì)返回一個(gè)靜態(tài)類型為你斷言的類型的對(duì)象,也就是說,當(dāng)我們使用了類型斷言,Go 實(shí)際上又會(huì)默認(rèn)為我們進(jìn)行了一次隱式的類型轉(zhuǎn)換。
驗(yàn)證方法也很簡(jiǎn)單,使用完一次類型斷言后,對(duì)返回的對(duì)象再一次使用類型斷言,Goland 立馬就會(huì)提示我們新對(duì)象 b 不是一個(gè)接口類型的對(duì)象,不允許進(jìn)行類型斷言。
總結(jié)
到此這篇關(guān)于Go 語(yǔ)言中關(guān)于接口的三個(gè)"潛規(guī)則"的文章就介紹到這了,更多相關(guān)go語(yǔ)言接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語(yǔ)言實(shí)現(xiàn)百萬(wàn)級(jí)WebSocket連接架構(gòu)設(shè)計(jì)及服務(wù)優(yōu)化
本文將詳細(xì)介紹如何在Go中構(gòu)建一個(gè)能夠支持百萬(wàn)級(jí)WebSocket連接的服務(wù),包括系統(tǒng)架構(gòu)設(shè)計(jì)、性能優(yōu)化策略以及具體的實(shí)現(xiàn)步驟和代碼示例2024-01-01Go語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單生產(chǎn)者消費(fèi)者模型
本文主要介紹了Go語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單生產(chǎn)者消費(fèi)者模型,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12基于golang如何實(shí)現(xiàn)error工具包詳解
Go 語(yǔ)言使用 error 類型來(lái)返回函數(shù)執(zhí)行過程中遇到的錯(cuò)誤,下面這篇文章主要給大家介紹了關(guān)于如何基于golang實(shí)現(xiàn)error工具包的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-09-09利用Go語(yǔ)言快速實(shí)現(xiàn)一個(gè)極簡(jiǎn)任務(wù)調(diào)度系統(tǒng)
任務(wù)調(diào)度(Task Scheduling)是很多軟件系統(tǒng)中的重要組成部分,字面上的意思是按照一定要求分配運(yùn)行一些通常時(shí)間較長(zhǎng)的腳本或程序。本文將利用Go語(yǔ)言快速實(shí)現(xiàn)一個(gè)極簡(jiǎn)任務(wù)調(diào)度系統(tǒng),感興趣的可以了解一下2022-10-10go語(yǔ)言發(fā)送smtp郵件的實(shí)現(xiàn)示例
這篇文章主要介紹了go發(fā)送smtp郵件的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09golang如何設(shè)置Header Content-type
這篇文章主要介紹了golang如何設(shè)置Header Content-type問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01Go檢查結(jié)構(gòu)體中是否存在某個(gè)字段及創(chuàng)建結(jié)構(gòu)體切片或映射
這篇文章主要為大家介紹了Go檢查結(jié)構(gòu)體中是否存在某個(gè)字段及創(chuàng)建結(jié)構(gòu)體切片或映射實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01