Go interface詳解

??如Go method中提及,Golang沒有明確支持多態(tài)统阿,但是通過其他手段可以實現(xiàn)類似C++中的多態(tài)特性玷氏,即本文中即將介紹的Go interface功能。

interface定義

??interface(接口)是golang最重要的特性之一摔蓝,Interface類型可以定義一組方法赂苗,但是這些不需要實現(xiàn)。請注意:此處限定是一組方法贮尉,既然是方法拌滋,就不能是變量;而且是一組猜谚,表明可以有多個方法败砂。再多聲明一點,interface本質(zhì)上是一種類型魏铅,確切的說昌犹,是指針類型,此處暫且不多表沦零,后文中自然能體會到祭隔。
??interface是為實現(xiàn)多態(tài)功能,多態(tài)是指代碼可以根據(jù)類型的具體實現(xiàn)采取不同行為的能力路操。如果一個類型實現(xiàn)了某個接口疾渴,所有使用這個接口的地方,都可以支持這種類型的值屯仗。

type  接口名稱 interface {
    method1(參數(shù)列表) 返回值列表
    method2(參數(shù)列表) 返回值列表
    ...
    methodn(參數(shù)列表) 返回值列表
}

??接口通常以er作為名稱后綴搞坝,方法名是聲明組成部分,但參數(shù)名可不同或省略魁袜。如果接口沒有任何方法聲明桩撮,那么就是一個空接口(interface{}),它的用途類似面向?qū)ο罄锏母愋蚈bject峰弹,可被賦值為任何類型的對象店量。接口變量默認值是nil。如果實現(xiàn)接口的類型支持鞠呈,可做相等運算融师。

func main() { 
   var t1,t2 interface{} 
   println(t1==nil,t1==t2) 
  
   t1,t2=100,100
   println(t1==t2) 
  
   t1,t2=map[string]int{},map[string]int{} 
   println(t1==t2) 
}

輸出為

true true
true
panic:runtime error:comparing uncomparable type map[string]int

??此外,還可以像匿名字段那樣蚁吝,嵌入其他接口旱爆。目標類型方法集中必須擁有包含嵌入接口方法在內(nèi)的全部方法才算實現(xiàn)了該接口舀射。

type stringer interface{ 
   string()string
} 
  
type tester interface{ 
   stringer               // 嵌入其他接口 
   test() 
} 
  
type data struct{} 
  
func(*data)test() {
} 

func(data)string()string{ 
   return""
} 
  
func main() { 
   var d data
  
   var t tester= &d
   t.test() 
   println(t.string()) 
}

interface應(yīng)用場景

類型轉(zhuǎn)換

??類型推斷可將接口變量還原為原始類型,或用來判斷是否實現(xiàn)了某個更具體的接口類型怀伦。

type data int
  
func(d data)String()string{ 
   return fmt.Sprintf("data:%d",d) 
} 
  
func main() { 
   var d data=15
   var x interface{} =d
  
   if n,ok:=x.(fmt.Stringer);ok{  // 轉(zhuǎn)換為更具體的接口類型 
       fmt.Println(n) 
    } 
  
   if d2,ok:=x.(data);ok{        // 轉(zhuǎn)換回原始類型 
       fmt.Println(d2) 
    } 
  
   e:=x.(error)           // 錯誤:main.data is not error
   fmt.Println(e) 
}

輸出為:

data:15
data:15
panic:interface conversion:main.data is not error:missing method Error

??但是此處會觸發(fā)panic脆烟,使用ok-idiom模式,即便轉(zhuǎn)換失敗也不會引發(fā)panic房待。還可用switch語句在多種類型間做出推斷匹配邢羔,這樣空接口就有更多發(fā)揮空間。

func main() {
var x interface{} =func(x int)string{ 
       return fmt.Sprintf("d:%d",x) 
    } 
  
   switch v:=x.(type) {            // 局部變量v是類型轉(zhuǎn)換后的結(jié)果 
   case nil: 
       println("nil") 
   case*int: 
       println(*v) 
   case func(int)string: 
       println(v(100)) 
   case fmt.Stringer: 
       fmt.Println(v) 
   default: 
       println("unknown") 
    } 
}

輸出為:

d:100

實現(xiàn)多態(tài)功能

??多態(tài)功能是interface實現(xiàn)的重要功能吴攒,也是Golang中的一大行為特色张抄,其多態(tài)功能一般要結(jié)合Go method實現(xiàn),作為函數(shù)參數(shù)可以容易的實現(xiàn)多臺功能洼怔。

package main

import "fmt"

// notifier是一個定義了通知類行為的接口
type notifier interface {
  notify()
}

// 定義user及user.notify方法
type user struct {
  name string
  email string
}

func (u *user) notify() {
  fmt.Printf("Sending user email to %s<%s>\n",
    u.name,
    u.email)
}

// 定義admin及admin.notify方法
type admin struct {
  name string
  email string
}

func (a *admin) notify() {
  fmt.Printf("Sending admin email to %s<%s>\n",
    a.name,
    a.email)
}

func main() {
  // 創(chuàng)建一個user值并傳給sendNotification
  bill := user{"Bill", "bill@email.com"}
  sendNotification(&bill)

  // 創(chuàng)建一個admin值并傳給sendNotification
  lisa := admin{"Lisa", "lisa@email.com"}
  sendNotification(&lisa)
}

// sendNotification接受一個實現(xiàn)了notifier接口的值
// 并發(fā)送通知
func sendNotification(n notifier) {
  n.notify()
}

??上述代碼中實現(xiàn)了一個多態(tài)的例子,函數(shù)sendNotification接受一個實現(xiàn)了notifier接口的值作為參數(shù)左驾。既然任意一個實體類型都能實現(xiàn)該接口镣隶,那么這個函數(shù)可以針對任意實體類型的值來執(zhí)行notify方法,調(diào)用notify時诡右,會根據(jù)對象的實際定義來實現(xiàn)不同的行為安岂,從而實現(xiàn)多態(tài)行為。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末帆吻,一起剝皮案震驚了整個濱河市域那,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌猜煮,老刑警劉巖次员,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異王带,居然都是意外死亡淑蔚,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門愕撰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刹衫,“玉大人,你說我怎么就攤上這事搞挣〈伲” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵囱桨,是天一觀的道長仓犬。 經(jīng)常有香客問我,道長蝇摸,這世上最難降的妖魔是什么婶肩? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任办陷,我火速辦了婚禮,結(jié)果婚禮上律歼,老公的妹妹穿的比我還像新娘民镜。我一直安慰自己,他們只是感情好险毁,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布制圈。 她就那樣靜靜地躺著,像睡著了一般畔况。 火紅的嫁衣襯著肌膚如雪鲸鹦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天跷跪,我揣著相機與錄音馋嗜,去河邊找鬼。 笑死吵瞻,一個胖子當著我的面吹牛葛菇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播橡羞,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼眯停,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了卿泽?” 一聲冷哼從身側(cè)響起莺债,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎签夭,沒想到半個月后齐邦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡覆致,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年侄旬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片煌妈。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡儡羔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出璧诵,到底是詐尸還是另有隱情汰蜘,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布之宿,位于F島的核電站族操,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜色难,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一泼舱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枷莉,春花似錦娇昙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹲盘,卻和暖如春股毫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背召衔。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工铃诬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人薄嫡。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓氧急,卻偏偏與公主長得像,于是被迫代替她去往敵國和親毫深。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容