golang學(xué)習(xí)筆記--Interface

什么是 Interface

在面向?qū)ο蟮氖澜缰校涌诘囊话愣x是“接口定義對(duì)象的行為”兔毙,即只定義對(duì)象的行為柠辞,至于對(duì)象如何行動(dòng)則具體實(shí)現(xiàn)在對(duì)象中。

在 Golang 中走触,接口是一組方法簽名晦譬,當(dāng)一個(gè)類型為接口中的所有方法提供定義時(shí),就說實(shí)現(xiàn)了該接口互广。接口指定類型應(yīng)具有的方法敛腌,類型決定如何實(shí)現(xiàn)這些方法。

接口的定義和實(shí)現(xiàn)

package main

import (  
    "fmt"
)

//interface definition
type VowelsFinder interface {  
    FindVowels() []rune
}

type MyString string

//MyString implements VowelsFinder
func (ms MyString) FindVowels() []rune {  
    var vowels []rune
    for _, rune := range ms {
        if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' {
            vowels = append(vowels, rune)
        }
    }
    return vowels
}

func main() {  
    name := MyString("Sam Anderson")
    var v VowelsFinder
    v = name // possible since MyString implements VowelsFinder
    fmt.Printf("Vowels are %c", v.FindVowels())

interface 應(yīng)用場(chǎng)景

類 java 中的多態(tài)

package main

import (  
    "fmt"
)
// 接口定義
type SalaryCalculator interface {  
    CalculateSalary() int
}
// 類型1
type Permanent struct {  
    empId    int
    basicpay int
    pf       int
}
// 類型2
type Contract struct {  
    empId  int
    basicpay int
}

// Permanent salary 計(jì)算實(shí)現(xiàn)
func (p Permanent) CalculateSalary() int {  
    return p.basicpay + p.pf
}

// Contract salary 計(jì)算實(shí)現(xiàn)
func (c Contract) CalculateSalary() int {  
    return c.basicpay
}

/*
通過對(duì)SalalCalculator切片進(jìn)行迭代并求和來計(jì)算總費(fèi)用個(gè)人雇員的工資
*/
func totalExpense(s []SalaryCalculator) {  
    expense := 0
    for _, v := range s {
        expense = expense + v.CalculateSalary()
    }
    fmt.Printf("Total Expense Per Month $%d", expense)
}

func main() {  
    pemp1 := Permanent{1, 5000, 20}
    pemp2 := Permanent{2, 6000, 30}
    cemp1 := Contract{3, 3000}
    employees := []SalaryCalculator{pemp1, pemp2, cemp1}
    totalExpense(employees)
}

在上述程序片段中惫皱,totalExpense 接收一個(gè) interface slice像樊,可以應(yīng)用于任何實(shí)現(xiàn)SalaryCalculator interface 的類型,若我們添加一個(gè)新的類型旅敷,實(shí)現(xiàn)一種新的薪資計(jì)算方式生棍,上述代碼可以完全不需要修改即可使用。

用于內(nèi)部表示

可以將接口視為由元組(類型媳谁,值)在內(nèi)部表示涂滴。type是接口的基礎(chǔ)具體類型,value持有具體類型的值晴音。

type Tester interface {  
    Test()
}

type MyFloat float64

func (m MyFloat) Test() {  
    fmt.Println(m)
}

func describe(t Tester) {  
    fmt.Printf("Interface type %T value %v\n", t, t)
}
func main() {  
    var t Tester
    f := MyFloat(89.7) 
    t = f               // 此處將類型賦值柔纵,
    describe(t)         // 此處的輸出為 Interface type main.MyFloat value 89.7  
    t.Test()
}

空接口

空接口中沒有任何方法,表示為 interface{}段多,由于空接口沒有任何方法首量,因此可以理解為所有類型默認(rèn)實(shí)現(xiàn)了此接口。

func describe(i interface{}) {  
    fmt.Printf("Type = %T, value = %v\n", i, i)
}

func main() {  
    s := "Hello World"
    describe(s)      // Type = string, value = Hello World  
    i := 55
    describe(i)      // Type = int, value = 55 
    strt := struct {
        name string
    }{
        name: "Naveen R",
    }
    describe(strt)   // Type = struct { name string }, value = {Naveen R}  
}

類型判定

可以使用語法 i.(T) 獲取變量i中T類型的值进苍,以此來判斷傳入的類型是否正確

s := i.(int) // 獲取變量 i 中 int 類型的數(shù)據(jù)加缘,若 i 不是 int, 則 panic
v, ok := i.(int) // 用這種方式避免 panic

此外觉啊,也可以配合 switch 實(shí)現(xiàn)類型判斷

func findType(i interface{}) {  
    switch i.(type) {
    case string:
        fmt.Printf("I am a string and my value is %s\n", i.(string))
    case int:
        fmt.Printf("I am an int and my value is %d\n", i.(int))
    default:
        fmt.Printf("Unknown type\n")
    }
}   

當(dāng)然拣宏,也可以將類型與接口進(jìn)行比較。如果我們有一個(gè)類型杠人,并且該類型實(shí)現(xiàn)了一個(gè)接口勋乾,則可以將該類型與其實(shí)現(xiàn)的接口進(jìn)行比較宋下。

type Describer interface {  
    Describe()
}
type Person struct {  
    name string
    age  int
}

func (p Person) Describe() {  
    fmt.Printf("%s is %d years old", p.name, p.age)
}

func findType(i interface{}) {  
    switch v := i.(type) {
    case Describer:
        v.Describe()
    default:
        fmt.Printf("unknown type\n")
    }
}

通過嵌入接口,實(shí)現(xiàn)繼承的功能

type SalaryCalculator interface {  
    DisplaySalary()
}

type LeaveCalculator interface {  
    CalculateLeavesLeft() int
}

type EmployeeOperations interface {  
    SalaryCalculator
    LeaveCalculator
}

type Employee struct {  
    firstName string
    lastName string
    basicPay int
    pf int
    totalLeaves int
    leavesTaken int
}

// Employee 實(shí)現(xiàn)了 DisplaySalary 和 CalculateLeavesLeft 兩個(gè)接口辑莫,也就默認(rèn)實(shí)現(xiàn)了 EmployeeOperations 接口
func (e Employee) DisplaySalary() {  
    fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf))
}

func (e Employee) CalculateLeavesLeft() int {  
    return e.totalLeaves - e.leavesTaken
}

func main() {  
    e := Employee {
        firstName: "Naveen",
        lastName: "Ramanathan",
        basicPay: 5000,
        pf: 200,
        totalLeaves: 30,
        leavesTaken: 5,
    }
    // 此處可以說 Employee 實(shí)現(xiàn)了 EmployeeOperations接口
    var empOp EmployeeOperations = e
    empOp.DisplaySalary()
    fmt.Println("\nLeaves left =", empOp.CalculateLeavesLeft())
}

接口的 0 值

接口的零值為nil学歧。
nil接口具有其基礎(chǔ)值和具體類型(如nil)。

type Describer interface {  
    Describe()
}

func main() {  
    var d1 Describer
    if d1 == nil {
        // 此處輸出  d1 is nil and has type <nil> value <nil> 
        fmt.Printf("d1 is nil and has type %T value %v\n", d1, d1)
    }
}

喜歡的話各吨,訪問我的主頁吧枝笨,請(qǐng)多關(guān)照!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揭蜒,一起剝皮案震驚了整個(gè)濱河市横浑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屉更,老刑警劉巖徙融,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異瑰谜,居然都是意外死亡欺冀,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門萨脑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脚猾,“玉大人,你說我怎么就攤上這事砚哗。” “怎么了砰奕?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵蛛芥,是天一觀的道長。 經(jīng)常有香客問我军援,道長仅淑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任胸哥,我火速辦了婚禮涯竟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘空厌。我一直安慰自己庐船,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布嘲更。 她就那樣靜靜地躺著筐钟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赋朦。 梳的紋絲不亂的頭發(fā)上篓冲,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天李破,我揣著相機(jī)與錄音,去河邊找鬼壹将。 笑死嗤攻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诽俯。 我是一名探鬼主播妇菱,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼惊畏!你這毒婦竟也來了恶耽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤颜启,失蹤者是張志新(化名)和其女友劉穎偷俭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缰盏,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涌萤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了口猜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片负溪。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖济炎,靈堂內(nèi)的尸體忽然破棺而出川抡,到底是詐尸還是另有隱情,我是刑警寧澤须尚,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布崖堤,位于F島的核電站,受9級(jí)特大地震影響耐床,放射性物質(zhì)發(fā)生泄漏密幔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一撩轰、第九天 我趴在偏房一處隱蔽的房頂上張望胯甩。 院中可真熱鬧,春花似錦堪嫂、人聲如沸偎箫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镜廉。三九已至,卻和暖如春愚战,著一層夾襖步出監(jiān)牢的瞬間娇唯,已是汗流浹背齐遵。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留塔插,地道東北人梗摇。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像想许,于是被迫代替她去往敵國和親伶授。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

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