Golang interface介面全面理解(一)

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

There are three kinds of time: the future is late, and now it is flying like an arrow. The past will never stand still.

時間的步伐有三種:未來姍姍來遲,現在像箭一般飛逝,過去永遠靜立不動。

什麼是interface

    在物件導向編程中,可以這麼說:“介面定義了對象的行為”, 那麼具體的實現行為就取決於對象了。

    在Go中,介面是一組方法簽名。當一個類型為介面中的所有方法提供定義時,它被稱為實現該介面。它與oop非常相似。介面指定類型應具有的方法,類型決定如何?這些方法。

建立和實現interface

在Golang中只要實現了介面定義的方法,就是(JAVA implement)實現了該interface 

package mainimport (      "fmt")//定義interface type VowelsFinder interface {      FindVowels() []rune}type MyString string//實現介面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     fmt.Printf("Vowels are %c", v.FindVowels())}

 

介面的實際用途

為什麼說是實際用途呢? 如果我們我上面code中的

fmt.Printf("Vowels are %c", v.FindVowels())

替換為

fmt.Printf("Vowels are %c", name.FindVowels())

程式同樣的輸出,而沒有使用我們定義的介面。(v變數刪除定義)

下面我們通過案例解釋:

    假設某公司有兩個員工,一個普通員工和一個進階員工, 但是基本薪資是相同的,進階員工多拿獎金。計算公司為員工的總開支。

package mainimport ("fmt")// 薪資計算機介面type SalaryCalculator interface {CalculateSalary() int}// 普通挖掘機員工type Contract struct {empId  intbasicpay int}// 有藍翔技校證的員工type Permanent struct {empId  intbasicpay intjj int // 獎金}func (p Permanent) CalculateSalary() int {return p.basicpay + p.jj}func (c Contract) CalculateSalary() int {return c.basicpay}// 總開支func totalExpense(s []SalaryCalculator) {expense := 0for _, v := range s {expense = expense + v.CalculateSalary()}fmt.Printf("總開支 $%d", expense)}func main() {pemp1 := Permanent{1,3000,10000}pemp2 := Permanent{2, 3000, 20000}cemp1 := Contract{3, 3000}employees := []SalaryCalculator{pemp1, pemp2, cemp1}totalExpense(employees)}

體驗一下使用介面的美感吧!

介面的內部表現

一個介面可以被認為是由一個元組(類型,值)在內部表示的。type是介面的基礎具體類型,value是具體類型的值。

package mainimport ("fmt")type Test interface {Tester()}type MyFloat float64func (m MyFloat) Tester() {fmt.Println(m)}func describe(t Test) {fmt.Printf("Interface 類型 %T ,  值: %v\n", t, t)}func main() {var t Testf := MyFloat(89.7)t = fdescribe(t)t.Tester()}

輸出:

Interface 類型 main.MyFloat ,  值: 89.7
89.7

空介面

具有0個方法的介面稱為空白介面。它表示為interface {}。由於空介面有0個方法,所有類型都實現了空介面。

package mainimport ("fmt")func describe(i interface{}) {fmt.Printf("Type = %T, value = %v\n", i, i)}func main() {     // 任何類型的變數傳入都可以s := "Hello World"i := 55strt := struct {name string}{name: "Naveen R",}describe(s)describe(i)describe(strt)}

 

類型斷言

類型斷言用於提取介面的基礎值,文法:i.(T)

package mainimport("fmt")func assert(i interface{}){    s:= i.(int)    fmt.Println(s)}func main(){  var s interface{} = 55  assert(s)}

程式列印的是int值, 但是如果我們給s 變數賦值的是string類型,程式就會panic。

所以可以將以上程式改寫為:

package mainimport (      "fmt")func assert(i interface{}) {      v, ok := i.(int)    fmt.Println(v, ok)}func main() {      var s interface{} = 56    assert(s)    var i interface{} = "Steven Paul"    assert(i)}

如果 i 的值是int類型, 那麼v就是i 對應的值, ok就是true。否則ok為false,程式並不會panic。

類型判斷

類型判斷的文法類似於類型斷言。在類型斷言的文法i.(type)中,類型type應該由類型轉換的關鍵字type替換。讓我們看看它如何在下面的程式中起作用。

package mainimport (      "fmt")func findType(i interface{}) {      switch i.(type) {    case string:        fmt.Printf("String: %s\n", i.(string))    case int:        fmt.Printf("Int: %d\n", i.(int))    default:        fmt.Printf("Unknown type\n")    }}func main() {      findType("Naveen")    findType(77)    findType(89.98)}

還可以將類型與介面進行比較。如果我們有一個類型並且該類型實現了一個介面,那麼可以將它與它實現的介面進行比較。

package mainimport "fmt"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")    }}func main() {      findType("Naveen")    p := Person{        name: "Naveen R",        age:  25,    }    findType(p)}

輸出:

unknown type  Naveen R is 25 years old  

 

最後,留一個小問題,猜想一下,下面程式的輸出結果:    

package mainimport "fmt"type Describer interface {      Describe()}type St stringfunc (s St) Describe() {      fmt.Println("被調用le!")}func findType(i interface{}) {      switch v := i.(type) {    case Describer:        v.Describe()    case string:        fmt.Println("String 變數")    default:        fmt.Printf("unknown type\n")    }}func main() {      findType("Naveen")    st := St("我的字串")    findType(p)}

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.