Go 之 interface接口理解

go語言並沒有面向對象的相關概念,go語言提到的接口和java、c++等語言提到的接口不同,它不會顯示的說明實現了接口,沒有繼承、子類、implements關鍵詞。go語言通過隱性的方式實現了接口功能,相對比較靈活。

interface是go語言的一大特性,主要有以下幾個特點:

  • interface 是方法或行爲聲明的集合
  • interface接口方式實現比較隱性,任何類型的對象實現interface所包含的全部方法,則表明該類型實現了該接口。
  • interface還可以作爲一中通用的類型,其他類型變量可以給interface聲明的變量賦值。
  • interface 可以作爲一種數據類型,實現了該接口的任何對象都可以給對應的接口類型變量賦值。

下面是一些代碼示例

接口實現

package main

import "fmt"

type Animal interface {
    GetAge() int32
    GetType() string
}

type Dog struct {
    Age  int32
    Type string
}

func (a *Dog) GetAge() int32 {
    return a.Age
}
func (a *Dog) GetType() string {
    return a.Type
}

func main() {
    animal := &Dog{Age: 20, Type: "DOG"}
    fmt.Printf("%s max age is: %d", animal.GetType(), animal.GetAge())

}

interface作爲通用類型

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Id     int
   Name   string
   Amount float64
}


func main() {
   var i interface{}
   i = "string"
   fmt.Println(i)
   i = 1
   fmt.Println(i)
   i = User{Id: 2}
   //i.(User).Id = 15  //運行此處會報錯,在函數中修改interface表示的結構體的成員變量的值,編譯時遇到這個編譯錯誤,cannot assign to i.(User).Id
   fmt.Println(i.(User).Id)
  }

interface接口查詢

接口查詢,在一個接口變量中,查詢所賦值的對象有沒有實現其他接口所有的方法的過程,就是查詢接口。即接口A實現了接口B中所有的方法,那麼通過查詢賦值A可以轉化爲B。

代碼示例

package main

import "fmt"

type Animal interface {
    GetAge() int32
    GetType() string
}
type AnimalB interface {
    GetAge() int32
}

type Dog struct {
    Age  int32
    Type string
}

func (a *Dog) GetAge() int32 {
    return a.Age
}
func (a *Dog) GetType() string {
    return a.Type
}

func main() {
    var animal Animal = &Dog{Age: 20, Type: "DOG"}
    fmt.Printf("%s max age is: %d", animal.GetType(), animal.GetAge())
    var animalb AnimalB = &Dog{Age: 20, Type: "DOG"}
    fmt.Printf("max age is: %d", animalb.GetAge())

    //這裏實現了animalb 轉化Animal接口
    val, ok := animalb.(Animal)
    if !ok {
        fmt.Println("ok")
    } else {
        fmt.Printf("%s max age is: %d", val.GetType(), val.GetAge())
    }
}

接口轉化很簡單

val, ok := animalb.(Animal)

注意,animalb 只有AnimalB所包含的方法GetAge()。

如果接口A的方法列表是接口B的方法列表的子集,那麼接口B可以賦值給接口A,反之則不行。

接口類型查詢

只能對interface{}類型的變量使用類型查詢

示例

package main

import "fmt"

type Animal interface {
    GetAge() int32
    GetType() string
}
type AnimalB interface {
    GetAge() int32
}

type Dog struct {
    Age  int32
    Type string
}

func (a *Dog) GetAge() int32 {
    return a.Age
}
func (a *Dog) GetType() string {
    return a.Type
}

func main() {
    var i interface{}
    //i = "ok"
    //方法一
    val, ok := i.(Animal)
    if !ok {
        fmt.Println("no")
    } else {
        fmt.Println(val.GetAge())
    }
    // 方法二
    switch val := i.(type) {
    case string:
        fmt.Println(val)
    case int:
        fmt.Println(val)
    default:
        fmt.Println(val)
    }
    // 方法三 通過反射
    typename := reflect.TypeOf(i)
    fmt.Println(typename)
}

interface默認nil所以查出是nil,如果給i賦值一個字符型值(去掉i = "ok"前面的註釋),則返回

no
ok
string

參考:

https://blog.csdn.net/hzwy23/...

https://www.cnblogs.com/zhang...

links

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章