嵌入類型,或者嵌套類型,這是一種可以把已有的類型聲明在新的類型里的一種方式,這種功能對(duì)代碼復(fù)用非常重要。
創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括新邱網(wǎng)站建設(shè)、新邱網(wǎng)站制作、新邱網(wǎng)頁(yè)制作以及新邱網(wǎng)絡(luò)營(yíng)銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,新邱網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到新邱省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!在其他語言中,有繼承可以做同樣的事情,但是在Go語言中,沒有繼承的概念。Go提倡的代碼復(fù)用的方式是組合,所以這也是嵌入類型的意義所在。組合而不是繼承,所以Go才會(huì)更靈活。
type Reader interface { Read(p []byte) (n int, err error) } type Writer interface { Write(p []byte) (n int, err error) } type Closer interface { Close() error } type ReadWriter interface { Reader Writer } type ReadCloser interface { Reader Closer } type WriteCloser interface { Writer Closer }
以上是標(biāo)準(zhǔn)庫(kù)io
包里我們常用的接口,可以看到ReadWriter
接口是嵌入Reader
和Reader
接口而組合成的新接口,這樣我們就不用重復(fù)地定義被嵌入接口里的方法,直接通過嵌入就可以了。嵌入類型同樣適用于結(jié)構(gòu)體類型,我們?cè)賮砜磦€(gè)例子:
type user struct { name string email string } type admin struct { user level string }
嵌入后,被嵌入的類型稱之為內(nèi)部類型,新定義的類型稱之為外部類型。這里user
就是內(nèi)部類型,而admin
是外部類型。
通過嵌入類型,與內(nèi)部類型相關(guān)聯(lián)的所有字段、方法、標(biāo)志符等,都會(huì)被外包類型所擁有。就像外部類型自己的一樣,這就達(dá)到了代碼快捷復(fù)用組合的目的,而且定義非常簡(jiǎn)單,只需聲明這個(gè)類型的名字就可以了。
同時(shí),外部類型還可以添加自己的方法、字段屬性等,可以很方便地?cái)U(kuò)展外部類型的功能。
func main() { ad:=admin{user{"張三","zhangsan@flysnow.org"},"管理員"} fmt.Println("可以直接調(diào)用,名字為:",ad.name) fmt.Println("也可以通過內(nèi)部類型調(diào)用,名字為:",ad.user.name) fmt.Println("但是新增加的屬性只能直接調(diào)用,級(jí)別為:",ad.level) }
以上是嵌入類型的使用??梢钥吹剑覀?cè)诔跏蓟臅r(shí)候,采用的是字面值的方式。所以要按其定義的結(jié)構(gòu)進(jìn)行初始化,先初始化user
這個(gè)內(nèi)部類型的,再初始化新增的level
屬性。
對(duì)于內(nèi)部類型的屬性和方法訪問,我們可以用外部類型直接訪問,也可以通過內(nèi)部類型進(jìn)行訪問;但是我們?yōu)橥獠款愋托略龅姆椒▽傩宰侄危荒苁褂猛獠款愋驮L問,因?yàn)閮?nèi)部類型沒有這些。
當(dāng)然,外部類型也可以聲明同名的字段或者方法,來覆蓋內(nèi)部類型的,這種情況方法比較多,我們以方法為例。
func main() { ad:=admin{user{"張三","zhangsan@flysnow.org"},"管理員"} ad.user.sayHello() ad.sayHello() } type user struct { name string email string } type admin struct { user level string } func (u user) sayHello(){ fmt.Println("Hello,i am a user") } func (a admin) sayHello(){ fmt.Println("Hello,i am a admin") }
內(nèi)部類型user
有一個(gè)sayHello
方法,外部類型對(duì)其進(jìn)行了覆蓋,同名重寫sayHello
,然后我們?cè)趍ain方法里分別訪問這兩個(gè)類型的方法,打印輸出:
Hello,i am a user Hello,i am a admin
從輸出中看,方法sayHello
被成功覆蓋了。
嵌入類型的強(qiáng)大,還體現(xiàn)在:如果內(nèi)部類型實(shí)現(xiàn)了某個(gè)接口,那么外部類型也被認(rèn)為實(shí)現(xiàn)了這個(gè)接口。我們稍微改造下例子看下。
func main() { ad:=admin{user{"張三","zhangsan@flysnow.org"},"管理員"} sayHello(ad.user)//使用user作為參數(shù) sayHello(ad)//使用admin作為參數(shù) } type Hello interface { hello() } func (u user) hello(){ fmt.Println("Hello,i am a user") } func sayHello(h Hello){ h.hello() }
這個(gè)例子原來的結(jié)構(gòu)體類型user
和admin
的定義不變,新增了一個(gè)接口Hello
,然后讓user
類型實(shí)現(xiàn)這個(gè)接口,最后我們定義了一個(gè)sayHello
方法,它接受一個(gè)Hello
接口類型的參數(shù)。最終我們?cè)趍ain函數(shù)演示的時(shí)候,發(fā)現(xiàn)不管是user
類型,還是admin
類型作為參數(shù)傳遞給sayHello
方法的時(shí)候,都可以正常調(diào)用。
這里就可以說明admin
實(shí)現(xiàn)了接口Hello
。但是我們又沒有顯示聲明類型admin
實(shí)現(xiàn),所以這個(gè)實(shí)現(xiàn)是通過內(nèi)部類型user
實(shí)現(xiàn)的;因?yàn)?code>admin包含了user
所有的方法函數(shù),所以也就實(shí)現(xiàn)了接口Hello
。
當(dāng)然外部類型也可以重新實(shí)現(xiàn),只需要像上面例子一樣覆蓋同名的方法即可。這里要說明的是,不管我們?nèi)绾瓮采w,都不會(huì)影響內(nèi)部類型,我們還可以通過訪問內(nèi)部類型來訪問它的方法、屬性字段等。
嵌入類型的定義,是Go為了方便我們擴(kuò)展或者修改已有類型的行為,是為了宣傳組合這個(gè)概念而設(shè)計(jì)的,所以我們經(jīng)常使用組合,靈活運(yùn)用組合,擴(kuò)展出更多的我們需要的類型結(jié)構(gòu)
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開啟,新人活動(dòng)云服務(wù)器買多久送多久。