如何判斷Golang接口是否實(shí)現(xiàn)的操作
前言
在看一個(gè)底層庫(kù)的的時(shí)候,看到了一個(gè)比較奇怪的寫(xiě)法,于是乎有了本文。
主要探討兩個(gè)問(wèn)題:
1.利用編譯來(lái)判斷Golang接口是否實(shí)現(xiàn)
2.延伸出的make和new的區(qū)別
正文
1.利用編譯來(lái)判斷Golang接口是否實(shí)現(xiàn)
看了一個(gè)底層通用鏈接池的庫(kù),有這么一行代碼:
var _ Pooler = new(WeightedRoundRobin)
需要解釋的是:Pooler是一個(gè)接口類型。
type Pooler interface { // ... }
剛開(kāi)始看是疑惑的,為什么new了之后是要拋棄調(diào)?
后面發(fā)現(xiàn)這個(gè)是為了驗(yàn)證某某接口是否被實(shí)現(xiàn)了?
多看了一些代碼后發(fā)現(xiàn)很多地方有類似這樣的寫(xiě)法。
至此Get到了。
解釋:如果說(shuō)次接口沒(méi)有被實(shí)現(xiàn),那么一方面ide會(huì)有紅橫線出現(xiàn),另一方面在編譯的時(shí)候會(huì)出現(xiàn)報(bào)錯(cuò)。兩方面的提示來(lái)保證寫(xiě)底層代碼的接口是有被實(shí)現(xiàn)的。
2.延伸出的make和new的區(qū)別
和小伙伴討論期間,跑出了這么一個(gè)問(wèn)題:“可以使用go test的方式,去_test.go文件中定義一個(gè)接口,來(lái)判斷就好了。上文判斷會(huì)存在浪費(fèi)內(nèi)存的情況”
這邊兩個(gè)點(diǎn):
1.go test的方式肯定是可行的。
但是并沒(méi)法保證程序員會(huì)真的記住去執(zhí)行進(jìn)行檢測(cè)(非強(qiáng)制必須走的流程)。但是直接通過(guò)前文方式,是會(huì)在編譯的時(shí)候拋錯(cuò)的,這個(gè)是必須走的流程,所以更推薦前文的方式。
2.new占內(nèi)存?
new:申請(qǐng)了內(nèi)存,但是不會(huì)將內(nèi)存初始化,只會(huì)將內(nèi)存置零,返回一個(gè)指針。
make:申請(qǐng)了內(nèi)存,返回已初始化的結(jié)構(gòu)體的零值。
回到正文,雖然申請(qǐng)了內(nèi)存,但占的內(nèi)存其實(shí)并不多,并且在初始化后的一次gc中便會(huì)回收。所以還好。
同時(shí)也不存在效率問(wèn)題,編譯型語(yǔ)言,你懂的。
同時(shí)驗(yàn)證一個(gè)new和取地址和make的區(qū)別的代碼:
func main() { a1 := new([]int) a2:= &[]int{} a3:= make([]int,0) fmt.Println(a1,a2,a3,a1==a1) }
輸出:
&[] &[] [] true
擴(kuò)展
對(duì)于內(nèi)存的占用,今天看到一種寫(xiě)法。
var _ Tester = (*Test)(nil)
這樣寫(xiě)和new的區(qū)別在于:new是編譯的時(shí)候檢查,這樣寫(xiě)是運(yùn)行的時(shí)候檢查
補(bǔ)充:Golang接口實(shí)現(xiàn)多態(tài)
我就廢話不多說(shuō)了,大家還是直接看代碼吧~
package main import ( "fmt" ) func main() { user := &User{name: "Chris"} user.ISubUser = &NormalUser{} user.sayHi() user.ISubUser = &ArtisticUser{} user.sayHi() } type ISubUser interface { sayType() } type User struct { name string ISubUser } func (u *User) sayHi() { u.sayName() u.sayType() } func (u *User) sayName() { fmt.Printf("I am %s.", u.name) } type NormalUser struct { } func (n *NormalUser) sayType() { fmt.Println("I am a normal user.") } type ArtisticUser struct { } func (a *ArtisticUser) sayType() { fmt.Println("I am an artistic user.") } //RUN 之后輸出: I am Chris.I am a normal user. I am Chris.I am a artistic user. //重用了sayName和sayHi方法,sayType方法可以多態(tài)來(lái)實(shí)現(xiàn)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
Golang使用Gin框架實(shí)現(xiàn)http分塊傳輸
這篇文章主要為大家詳細(xì)介紹了Golang中如何使用Gin框架實(shí)現(xiàn)http分塊傳輸功能,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的可以參考一下2023-05-05Go語(yǔ)言sync.Map詳解及使用場(chǎng)景
Go語(yǔ)言中的sync.Map是一個(gè)高效的并發(fā)安全映射結(jié)構(gòu),適用于高并發(fā)讀多寫(xiě)少的場(chǎng)景,它通過(guò)讀寫(xiě)分離、無(wú)鎖讀取路徑、寫(xiě)入時(shí)的鎖保護(hù)等機(jī)制,提高了讀取性能并減少了鎖競(jìng)爭(zhēng),sync.Map不需要手動(dòng)管理鎖,降低了編程復(fù)雜性,適合需要簡(jiǎn)單并發(fā)訪問(wèn)的場(chǎng)合2024-10-10使用golang實(shí)現(xiàn)一個(gè)MapReduce的示例代碼
這篇文章主要給大家介紹了關(guān)于如何使用golang實(shí)現(xiàn)一個(gè)MapReduce,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09Go語(yǔ)言中使用 buffered channel 實(shí)現(xiàn)線程安全的 pool
這篇文章主要介紹了Go語(yǔ)言中使用 buffered channel 實(shí)現(xiàn)線程安全的 pool,因?yàn)镚o語(yǔ)言自帶的sync.Pool并不是很好用,所以自己實(shí)現(xiàn)了一線程安全的 pool,需要的朋友可以參考下2014-10-10使用Go語(yǔ)言編寫(xiě)一個(gè)極簡(jiǎn)版的容器Container
Docker作為一種流行的容器化技術(shù),對(duì)于每一個(gè)程序開(kāi)發(fā)者而言都具有重要性和必要性,因?yàn)槿萜骰嚓P(guān)技術(shù)的普及大大簡(jiǎn)化了開(kāi)發(fā)環(huán)境配置、更好的隔離性和更高的安全性,對(duì)于部署項(xiàng)目和團(tuán)隊(duì)協(xié)作而言也更加方便,本文將嘗試使用Go語(yǔ)言編寫(xiě)一個(gè)極簡(jiǎn)版的容器2023-10-10Go外部依賴包從vendor,$GOPATH和$GOPATH/pkg/mod查找順序
這篇文章主要介紹了Go外部依賴包vendor,$GOPATH和$GOPATH/pkg/mod下查找順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12