成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

golang的接口有啥用

在golang中,接口是一種類型,是用來將對方法進(jìn)行一個收束,其作用是:1、作為方法的收束器,進(jìn)行面向?qū)ο笤O(shè)計;2、作為各種數(shù)據(jù)的承載者,可以用來接收函數(shù)參數(shù)等。接口的定義語法“type 接口類型名 interface{方法名( 參數(shù)列表1 ) 返回值列表}”;當(dāng)方法名首字母是大寫且這個接口類型名首字母也是大寫時,這個方法可以被接口所在的包(package)之外的代碼訪問。

golang的接口有啥用

本教程操作環(huán)境:windows7系統(tǒng)、GO 1.18版本、Dell G3電腦。

一、接口(interface)是什么

interface是一組method簽名的組合,我們通過interface來定義對象的一組行為。

(注意method 和普通func的區(qū)別)

Interface是一種類型,和往常語言的接口不一樣,它只是用來將對方法進(jìn)行一個收束。然而正是這種收束,使GO語言擁有了基于功能的面向?qū)ο蟆?/p>

接口的主要功能:

1.作為方法的收束器,進(jìn)行面向?qū)ο笤O(shè)計。

2.作為各種數(shù)據(jù)的承載者,可以用來接收函數(shù)參數(shù)等。

這也是,GO語言提倡面向接口編程

二、接口的定義使用

2.1定義

類似結(jié)構(gòu)體

type 接口類型名 interface{     方法名1( 參數(shù)列表1 ) 返回值列表1     方法名2( 參數(shù)列表2 ) 返回值列表2     … }
登錄后復(fù)制

當(dāng)然這只是有方法的接口定義,面向數(shù)據(jù)的接口不用。

  • 接口名:使用type將接口定義為自定義的類型名。Go語言的接口在命名時,一般會在單詞后面添加er,如有寫操作的接口叫Writer,有字符串功能的接口叫Stringer等。接口名最好要能突出該接口的類型含義。

  • 方法名:當(dāng)方法名首字母是大寫且這個接口類型名首字母也是大寫時,這個方法可以被接口所在的包(package)之外的代碼訪問。

  • 參數(shù)列表、返回值列表:參數(shù)列表和返回值列表中的參數(shù)變量名可以省略

2.2使用

一個對象只要全部實(shí)現(xiàn)了接口中的方法,那么就實(shí)現(xiàn)了這個接口。換句話說,接口就是一個需要實(shí)現(xiàn)的方法列表

//定義接口 type FastfoodStore interface{     MakeHamberger()     MakeFriedChips()     MakeSoftDrink() } //定義結(jié)構(gòu)體 type KFC struct{} type HambergerKing struct{}  //實(shí)現(xiàn)了接口中所有的方法 func (kfc KFC) MakeHamberger(){     fmt.println("肯德基的漢堡") } func (kfc KFC) MakeFriedChips(){     fmt.println("肯德基的薯條") } func (kfc KFC) MakeSoftDrink(){     fmt.println("肯德基的飲料") }  func (K *HambergerKing) MakeHameberger(){     fmt.println("漢堡王的漢堡") } func (K *HambergerKing) MakeFriedChips(){     fmt.println("漢堡王的薯條") } func (K *HambergerKing) MakeSoftDrink(){     fmt.println("漢堡王的飲料") }
登錄后復(fù)制

我們可以看到不同于Java的接口顯式實(shí)現(xiàn),Go的語言是隱式實(shí)現(xiàn)的。

  • 在 Java 中:實(shí)現(xiàn)接口需要顯式地聲明接口并實(shí)現(xiàn)所有方法;
  • 在 Go 中:實(shí)現(xiàn)接口的所有方法就隱式地實(shí)現(xiàn)了接口;

那么GO語言是如何檢查該類型是否是接口呢?

答:Go 語言只會在傳遞參數(shù)、返回參數(shù)以及變量賦值時才會對某個類型是否實(shí)現(xiàn)接口進(jìn)行檢查。從類型檢查的過程來看,編譯器僅在需要時才檢查類型,類型實(shí)現(xiàn)接口時只需要實(shí)現(xiàn)接口中的全部方法,不需要像 Java 等編程語言中一樣顯式聲明。

我們可以看到在上面實(shí)現(xiàn)接口的時候,KFC是用結(jié)構(gòu)體對象實(shí)現(xiàn)的,而Hamberger king是通過指針實(shí)現(xiàn)的兩者有什么不同呢?

答:區(qū)別在于我們初始化接口的時候

//結(jié)構(gòu)體初始化和指針初始化 var f faststore = KFC{}             //可以通過編譯 var f faststore = &KFC{}            //可以通過編譯  var f faststore = HambergerKing{}    //無法通過編譯 var f faststore = &HambergerKing{}    //可以通過編譯
登錄后復(fù)制

所以在我們使用指針進(jìn)行實(shí)現(xiàn),結(jié)構(gòu)體初始化時,為啥不行呢?

答:Go 語言在傳遞參數(shù)時都是傳值的。

golang的接口有啥用

如上圖所示,無論上述代碼中初始化的變量指針還是結(jié)構(gòu)體,使用 調(diào)用方法時都會發(fā)生值拷貝:

如上圖左側(cè),對于 &HambergerKing{} 來說,這意味著拷貝一個新的 &HambergerKing{} 指針,這個指針與原來的指針指向一個相同并且唯一的結(jié)構(gòu)體,所以編譯器可以隱式的對變量解引用(dereference)獲取指針指向的結(jié)構(gòu)體;
如上圖右側(cè),對于 HambergerKing{} 來說,這意味著方法會接受一個全新的 HambergerKing{},因為方法的參數(shù)是*HambergerKing,編譯器不會無中生有創(chuàng)建一個新的指針;即使編譯器可以創(chuàng)建新指針,這個指針指向的也不是最初調(diào)用該方法的結(jié)構(gòu)體;
上面的分析解釋了指針類型的現(xiàn)象,當(dāng)我們使用指針實(shí)現(xiàn)接口時,只有指針類型的變量才會實(shí)現(xiàn)該接口;當(dāng)我們使用結(jié)構(gòu)體實(shí)現(xiàn)接口時,指針類型和結(jié)構(gòu)體類型都會實(shí)現(xiàn)該接口。當(dāng)然這并不意味著我們應(yīng)該一律使用結(jié)構(gòu)體實(shí)現(xiàn)接口,這個問題在實(shí)際工程中也沒那么重要,在這里我們只想解釋現(xiàn)象背后的原因。

在上面我們說過,interface有兩種用法,現(xiàn)在介紹了其中一種就是作為方法的收束器。那么第二種就是作為數(shù)據(jù)的承載者

2.3 數(shù)據(jù)承載者

作為數(shù)據(jù)容器時,接口就是一個“空”接口,這個空來形容沒有Method。空interface(interface{})不包含任何的method,正因為如此,所有的類型都實(shí)現(xiàn)了空interface。空interface對于描述起不到任何的作用(因為它不包含任何的method),但是空interface在我們需要存儲任意類型的數(shù)值的時候相當(dāng)有用,因為它可以存儲任意類型的數(shù)值。它有點(diǎn)類似于C語言的void*類型。

需要注意的是,與 C 語言中的 void * 不同,interface{} 類型不是任意類型。如果我們將類型轉(zhuǎn)換成了 interface{} 類型,變量在運(yùn)行期間的類型也會發(fā)生變化,獲取變量類型時會得到 interface{}。

我們嘗試從底層實(shí)現(xiàn)來解釋兩種用法的不同,你會好理解一些。Go 語言使用 runtime.iface 表示第一種接口,使用 runtime.eface 表示第二種不包含任何方法的接口 interface{},兩種接口雖然都使用 interface 聲明,但是由于后者在 Go 語言中很常見,所以在實(shí)現(xiàn)時使用了特殊的類型。

golang的接口有啥用

空接口作為函數(shù)的參數(shù)

使用空接口實(shí)現(xiàn)可以接收任意類型的函數(shù)參數(shù)。

// 空接口作為函數(shù)參數(shù) func show(a interface{}) {     fmt.Printf("type:%T value:%vn", a, a) }
登錄后復(fù)制

空接口作為map的值

使用空接口實(shí)現(xiàn)可以保存任意值的字典。

// 空接口作為map值     var studentInfo = make(map[string]interface{})     studentInfo["name"] = "Wilen"     studentInfo["age"] = 18     studentInfo["married"] = false     fmt.Println(studentInfo) //gin框架的gin.H{}
登錄后復(fù)制

三、關(guān)于接口類型轉(zhuǎn)換

interface 可以存儲所有的值,那么自然會涉及到類型轉(zhuǎn)換這個話題。與此同時,我們也將在這節(jié)細(xì)說類型轉(zhuǎn)換中,因為結(jié)構(gòu)體實(shí)現(xiàn)和結(jié)構(gòu)體指針實(shí)現(xiàn)的接口的異同。

3.1結(jié)構(gòu)體指針實(shí)現(xiàn)接口

//我們?nèi)匀贿\(yùn)用上面快餐店的例子 type Store interface{     MakeHamberger() } type KFC struct{     name string } func (k *KFC) MakeHamberger(){     fmt.println(k.name+"制作了一個漢堡") } func main(){     var s store = &KFC{name:"東街店"}     store.MakeHamberger() }
登錄后復(fù)制

這里將上述代碼生成的匯編指令拆分成三部分分析:

1.結(jié)構(gòu)體 KFC 的初始化;

KFC的初始化又可以分為下面幾步:

  • 獲取 KFC 結(jié)構(gòu)體類型指針并將其作為參數(shù)放到棧上;

  • 通過 CALL 指定調(diào)用 runtime.newobject函數(shù),這個函數(shù)會以 KFC 結(jié)構(gòu)體類型指針作為入?yún)ⅲ峙湟黄碌膬?nèi)存空間并將指向這片內(nèi)存空間的指針返回到 SP+8 上;

  • SP+8 現(xiàn)在存儲了一個指向 KFC 結(jié)構(gòu)體的指針,我們將棧上的指針拷貝到寄存器 DI 上方便操作;

  • 由于 Cat 中只包含一個字符串類型的 Name 變量,所以在這里會分別將字符串地址 &"東街店" 和字符串長度 6 設(shè)置到結(jié)構(gòu)體上。

golang的接口有啥用

2.賦值觸發(fā)的類型轉(zhuǎn)換過程;

因為 KFC 結(jié)構(gòu)體的定義中只包含一個字符串,而字符串在 Go 語言中總共占 16 字節(jié),所以每一個 KFC 結(jié)構(gòu)體的大小都是 16 字節(jié)。初始化 KFC 結(jié)構(gòu)體之后就進(jìn)入了將 *KFC 轉(zhuǎn)換成 Store 類型的過程了:

類型轉(zhuǎn)換的過程比較簡單,Store 作為一個包含方法的接口,它在底層使用 [runtime.iface] 結(jié)構(gòu)體表示。runtime.iface 結(jié)構(gòu)體包含兩個字段,其中一個是指向數(shù)據(jù)的指針,另一個是表示接口和結(jié)構(gòu)體關(guān)系的 tab 字段,我們已經(jīng)通過上一段代碼 SP+8 初始化了 KFC 結(jié)構(gòu)體指針,這段代碼只是將編譯期間生成的 runtime.itab 結(jié)構(gòu)體指針復(fù)制到 SP 上:

golang的接口有啥用

到這里,我們會發(fā)現(xiàn) SP ~ SP+16 共同組成了 runtime.iface 結(jié)構(gòu)體。

3.調(diào)用接口的方法 Quack();

棧上的這個 runtime.iface 也是 MakeHamberger() 方法的第一個入?yún)ⅰMㄟ^CALL()完成方法的調(diào)用。

3.2 結(jié)構(gòu)體實(shí)現(xiàn)接口

//我們?nèi)匀贿\(yùn)用上面快餐店的例子 type Store interface{     MakeHamberger() } type KFC struct{     name string } func (k KFC) MakeHamberger(){     fmt.println(k.name+"制作了一個漢堡") } func main(){     var s store = KFC{name:"東街店"}     store.MakeHamberger() }
登錄后復(fù)制

如果我們在初始化變量時使用指針類型 &KFC{Name: "東街店"} 也能夠通過編譯,不過生成的匯編代碼和上一節(jié)中的幾乎完全相同,所以這里也就不分析這個情況了。

初始化 KFC 結(jié)構(gòu)體;

在棧上初始化 KFC 結(jié)構(gòu)體,而上一節(jié)的代碼在堆上申請了 16 字節(jié)的內(nèi)存空間,棧上只有一個指向 KFC 的指針。

完成從 KFC 到 Store 接口的類型轉(zhuǎn)換;

初始化結(jié)構(gòu)體后會進(jìn)入類型轉(zhuǎn)換的階段,編譯器會將 go.itab."".KFC,"".Store 的地址和指向 KFC 結(jié)構(gòu)體的指針作為參數(shù)一并傳入 runtime.convT2I 函數(shù):這個函數(shù)會獲取 runtime.itab 中存儲的類型,根據(jù)類型的大小申請一片內(nèi)存空間并將 elem 指針中的內(nèi)容拷貝到目標(biāo)的內(nèi)存中:

func convT2I(tab *itab, elem unsafe.Pointer) (i iface) {     t := tab._type     x := mallocgc(t.size, t, true)     typedmemmove(t, x, elem)     i.tab = tab     i.data = x     return }
登錄后復(fù)制

runtime.convT2I 會返回一個 runtime.iface,其中包含 runtime.itab 指針和 KFC 變量。當(dāng)前函數(shù)返回之后,main 函數(shù)的棧上會包含以下數(shù)據(jù):

golang的接口有啥用

SP 和 SP+8 中存儲的 runtime.itab 和 KFC 指針是 runtime.convT2I 函數(shù)的入?yún)ⅲ@個函數(shù)的返回值位于 SP+16,是一個占 16 字節(jié)內(nèi)存空間的 runtime.iface 結(jié)構(gòu)體,SP+32 存儲的是在棧上的 KFC 結(jié)構(gòu)體,它會在 runtime.convT2I 執(zhí)行的過程中拷貝到堆上。

3.3類型斷言

如何將一個接口類型轉(zhuǎn)換成具體類型?

x.(T)

非空接口

func main() {     var c Store = &KFC{Name: "東街店"}     switch c.(type) {     case *KFC:         kfc := c.(*KFC)         kfc.MakeHamberger()     } }
登錄后復(fù)制

因為 Go 語言的編譯器做了一些優(yōu)化,所以代碼中沒有runtime.iface 的構(gòu)建過程,不過對于這一節(jié)要介紹的類型斷言和轉(zhuǎn)換沒有太多的影響。

switch語句生成的匯編指令會將目標(biāo)類型的 hash 與接口變量中的 itab.hash 進(jìn)行比較

空接口

func main() {     var c interface{} = &KFC{Name: "東街店"}     switch c.(type) {     case *KFC:         kfc := c.(*KFC)         kfc.MakeHamberger()     } }
登錄后復(fù)制

上述代碼會在類型斷言時就不是直接獲取變量中具體類型的 runtime._type,而是從 eface._type 中獲取,匯編指令仍然會使用目標(biāo)類型的 hash 與變量的類型比較.

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
亚洲METART人体欣赏| 亚洲精品偷拍自综合网| 亚洲AV高清在线一区二区三区| 亚洲AⅤ男人的天堂在线观看| 亚洲AV无码成人精品区毛片| 亚洲丰满性熟妇ⅩXXOOO| 亚洲同性男GV网站SEARCH| 再深点灬舒服灬太大了AV| 99RE8这里有精品热视频| JK白丝极品被CAO到流水呻吟| 厨房掀开馊了裙子挺进电影| 国产精品无码一区二区三区不卡| 狠狠躁狠狠躁东京热无码专区| 久久久久久精品免费无码无| 欧美1卡2卡3卡4卡免费高清| 日韩一区二区三区北条麻妃| 西西人体大胆牲交视频| 亚洲熟妇色自偷自拍另类| √天堂网WWW最新版| 人妻在夫面前被性爆| 少妇CHINA中国人妻VIDE| 亚洲 校园 欧美 国产 另类| 野花新免费高清完整在线观看| ACTION对魔忍| 国产精品 高清 尿 小便 嘘嘘 | 98精产国品一二三产区区| 大白肥妇BBVBBW高潮| 国产天堂AV手机在线| 久久亚洲AⅤ精品网站婷婷| 人妻无码久久中文字幕专区| 午夜.DJ高清在线播放视频| 亚洲中字无码AV电影在线观看| JAPANESE国产在线看| 国产裸拍裸体视频在线观看| 久久一日本道色综合久久| 日韩成人一区二区三区在线观看 | 日本适合十八岁以上人群的护肤品| 无码熟妇人妻AV影片在线| 一級黃色毛片免費看| 丁香五月缴情网站| 九九九国产精品成人免费视频| 欧洲精品一线二线三线区别| 香蕉直播永久免费版APP| 中文字幕久无码免费久久| 国产AV成人一区二区三区| 久久久久久精品免费不卡| 日韩AV无码精品一二三区| 亚洲国产精品无码久久电影| www.av在线.com| 黑人精品一区二区| 欧美一区二期三区视频| 亚洲AV无码专区国产乱码在线观| 中文字幕日韩精品无码内射| 国产精品国产三级国产AN| 男人扒开女人的腿做爽爽视频| 无码人妻AⅤ一区二区三区蜜桃| 中文WWW新版资源在线| 国产精品亚洲LV粉色| 欧美VA久久久噜噜噜久久| 学长别揉了~流水了想要~| FREE性满足HD| 精品国产国偷自产在线观看| 日韩乱码人妻无码中文字幕视频 | 无码专区国产精品视频| 12孩岁女A处破娇小| 国精产品一码二码三M| 欧美人与人动人物2020| 亚洲精品无码鲁网中文电影| 俄罗斯美女做爰XXXⅩ啪啪| 久久香港三级台湾三级播放| 无码人妻精品中文字幕免费| CHINA末成年VIDEO学生| 精品人妻无码中字系列| 视频一区二区三区在线观看蜜桃| 在线观看韩国电影| 韩漫漫画无遮挡免费| 日韩精品无码一区二区三区AV | 理论片午午伦夜理片1| 性色ΑV一二三天美传媒| 被村长狂躁俩小时玉婷视频| 老师的粉嫩小又紧水又多| 亚洲AVT无码天堂网| 成人伊人亚洲人综合网站| 蜜桃av中文字幕| 亚洲国产美女精品久久久 | 日日噜噜夜夜狠狠久久无码区| 欲香欲色天天天综合和网| 好吊妞国产欧美日韩免费观看| 色欲色香天天天综合VVV| 9久9久女女免费视频精品| 久久久久国色AⅤ免费看| 亚洲AV成人片色在线观看| 高清FREESEXMOVIES性TV出水| 女性の乳頭を遮住する方法| 亚洲资源AV无码日韩AV无码 | 亚洲AV极品熟妇一品二品三品 | 涩爱AV挺进少妇张开双暴躁| CSGO内射最强对手| 美女裸体A级毛片| 亚洲人成人网站色www小说| 国产免费无遮挡吸奶头视频| 色一情一区二区三区四区| YSL万人千色T9| 男女啪啪无遮挡免费网站| 夜间十八款禁用软件APP下载| 韩国无码AV片在线观看| 无人区卡一卡二卡三乱码入口 | 51精产国品一二三产区区别| 久久久久精品精品6精品精品| 亚洲不卡无码AV中文字幕| 国产伦理一区二区| 天堂√中文最新版在线| 波多野AV一区二区无码| 欧洲无码一区二区三区在线观看 | 男人激烈吮乳吃奶动态图| 在C点用力把桌腿A抬离地面时游| 精品亚洲成在人线AV无码 | 狠狠噜天天噜日日噜| 新版天堂8中文在线最新版官网| 国产AV午夜精品一区二区入口| 日本亚欧乱色视频免费观看| 啊灬啊灬快灬高潮了视频| 欧美国产一区二区三区激情无套| 最新亚洲人成网站在线观看| 麻豆影视视频高清在线观看| 婬乱丰满熟妇XXXXⅩ性| 久久亚洲AV成人无码精品| 一二三四五在线播放免费观看中文| 久久精品国产免费播高清无卡| 亚洲日韩AV一区二区三区中文| 精品人妻AV一区二区三区| 亚洲欧洲无码精品ⅤA| 久久AV无码精品人妻系列果冻| 亚洲区小说区图片区QVOD| 久久精品国产99精品国产202| 亚洲欧美乱综合图片区小说区| 久爱无码精品免费视频在线观看| 亚洲色丰满少妇高潮18P| 久久久亚洲欧洲日产国码ΑV| 一区二区AV在线| 免费人成在线观看| 99久热RE在线精品视频| 屁屁影院最新发布页CCYY| 波多野结衣在线播放| 色一情一乱一伦一区二区三区 | MM131美女大尺度私密照尤果| 欧美性BBBBBXXXXX4050免费看| 暗交小拗女一区二区三区| 色婷婷AV一区二区三区| 国产成人综合亚洲AV| 亚洲 日韩 欧美 成人 在线观| 激情综合婷婷丁香五月俺来也| 亚洲人成伊人成综合网久久久| 久久久无码精品亚洲日韩精东传媒| 在线观看内射亲妹妹无套内射| 欧美丰满美乳XXⅩ高潮| 草莓榴莲秋葵绿丝污免费版18| 四虎国产精品永久在线| 国产午夜无码精品免费看动漫 | 精品久久久无码人妻中文字幕豆芽 | 日本亲与子乱人妻HD| 国产丰满老熟女重口对白| 亚洲AV午夜成人影院老师机影院 | 漂亮人妻洗澡被强人人躁| 丰满人妻少妇无码喷水| 午夜DJ免费完整在线看网| 久久996RE热这里只有精品无| 中文字幕人妻成人综合永久 | 成人无码影片精品久久久| 无码少妇一区二区浪潮免费| 精品国产一区二区三区AV性色| 在线观看一区二区三区AV| 漂亮人妻洗澡被公强BD| 国产精品成人无码久久久| 亚洲国产精品一区二区美利坚 | 99久久精品国产一区二区蜜芽| 日日摸日日碰夜夜爽97| 国语自产拍精品香蕉在线播放| 玉米地诱子偷伦初尝云雨孽欲| 人妻互换精品一区二区| 国产免费无码一区二区| 伊人久久亚洲综合AV影院| 人妖CHINESECDTS在线| 国产情侣一区二区三区| 治愈系恋人 电视剧| 色噜噜狠狠色综合久色AⅤ网| 皇上捏住宫女的巨峰| 7777久久亚洲中文字幕| 丝袜老师办公室里做好紧好爽| 精品欧美一区二区在线观看| AV无码精品一区二区三区四区| 婷婷妺妺窝人体色www久久| 久久精品国产99国产精品亚洲 | 日产精品一二三区| 河南妇女毛深深的沟WCD| ACCA少女SDANVI| 亚洲ⅤA中文字幕无码毛片| 男生把感叹号放进女生的括号| 国产精彩乱子真实视频| 中文人妻无码一区二区三区在线 |