天天看點

接口多實作,嵌套,空接口

Go語言基礎之接口多實作,嵌套,空接口

一、類型與接口的關系

一個類型實作多個接口

一個類型可以同時實作多個接口,而接口間彼此獨立,不知道對方的實作。 例如,狗可以叫,也可以動。我們就分别定義Sayer接口和Mover接口,如下:

Mover

接口。

// Sayer 接口
type Sayer interface {
    say()
}

// Mover 接口
type Mover interface {
    move()
}
           

dog既可以實作Sayer接口,也可以實作Mover接口。

type dog struct {
    name string
}

// 實作Sayer接口
func (d dog) say() {
    fmt.Printf("%s會叫汪汪汪\n", d.name)
}

// 實作Mover接口
func (d dog) move() {
    fmt.Printf("%s會動\n", d.name)
}

func main() {
    var x Sayer
    var y Mover

    var a = dog{name: "旺财"}
    x = a
    y = a
    x.say()
    y.move()
}
           

二、多個類型實作同一接口

Go語言中不同的類型還可以實作同一接口 首先我們定義一個

Mover

接口,它要求必須由一個

move

方法。

// Mover 接口
type Mover interface {
    move()
}
           

例如狗可以動,汽車也可以動,可以使用如下代碼實作這個關系:

type dog struct {
    name string
}

type car struct {
    brand string
}

// dog類型實作Mover接口
func (d dog) move() {
    fmt.Printf("%s會跑\n", d.name)
}

// car類型實作Mover接口
func (c car) move() {
    fmt.Printf("%s速度70邁\n", c.brand)
}
           

這個時候我們在代碼中就可以把狗和汽車當成一個會動的物體來處理了,不再需要關注它們具體是什麼,隻需要調用它們的

move

方法就可以了。

func main() {
    var x Mover
    var a = dog{name: "旺财"}
    var b = car{brand: "保時捷"}
    x = a
    x.move()
    x = b
    x.move()
}
           

上面的代碼執行結果如下:

旺财會跑
保時捷速度70邁
           

三、結構體類型嵌套

一個接口的方法,不一定需要由一個類型完全實作,接口的方法可以通過在類型中嵌入其他類型或者結構體來實作。

// WashingMachine 洗衣機
type WashingMachine interface {
    wash()
    dry()
}

// 甩幹器
type dryer struct{}

// 實作WashingMachine接口的dry()方法
func (d dryer) dry() {
    fmt.Println("甩一甩")
}

// 海爾洗衣機
type haier struct {
    dryer //嵌入甩幹器
}

// 實作WashingMachine接口的wash()方法
func (h haier) wash() {
    fmt.Println("洗刷刷")
}
           
var w WashingMachine = &haier{}
w.wash()
w.dry()

           

洗刷刷

甩一甩

四、接口嵌套

接口與接口間可以通過嵌套創造出新的接口。

// Sayer 接口
type Sayer interface {
    say()
}

// Mover 接口
type Mover interface {
    move()
}

// 接口嵌套
type animal interface {
    Sayer
    Mover
}
           

嵌套得到的接口的使用與普通接口一樣,這裡我們讓cat實作animal接口:

type cat struct {
    name string
}

func (c cat) say() {
    fmt.Println("喵喵喵")
}

func (c cat) move() {
    fmt.Println("貓會動")
}

func main() {
    var x animal
    x = cat{name: "花花"}
    x.move()
    x.say()
}
           

五、空接口

空接口的定義

空接口是指沒有定義任何方法的接口。是以任何類型都實作了空接口。

空接口類型的變量可以存儲任意類型的變量。

func main() {
    // 定義一個空接口x
    var x interface{}
    s := "Hello word"
    x = s
    fmt.Printf("type:%T value:%v\n", x, x)
    i := 100
    x = i
    fmt.Printf("type:%T value:%v\n", x, x)
    b := true
    x = b
    fmt.Printf("type:%T value:%v\n", x, x)
}
           

5.1空接口作為函數的參數

// 空接口作為函數參數
func show(a interface{}) {
    fmt.Printf("type:%T value:%v\n", a, a)
}
           

5.2 空接口作為map的值

// 空接口作為map值
var studentInfo = make(map[string]interface{})
studentInfo["name"] = "randy"
studentInfo["age"] = 18
studentInfo["married"] = false
fmt.Println(studentInfo)
           

六、總結

  1. 可以多個類型/結構體實作同一個接口,也可以一個類型實作多個接口
  2. 一個接口可以包含一個或多個其他的接口,這相當于直接将這些内嵌接口的方法列舉在外層接口中一樣
  3. 空接口指的是沒有規定任何方法接口,是以說,任意類型都算是實作了空接口,任意類型也都可以指派空接口類型的變量
  4. 接口作為map值的時,取出的值不是對應的類型,而是接口的類型,比如存入一個數值型,

    studentInfo["age"] + 1

    ,不能直接參與運算,需要通過斷言的方式進行相應操作。

在當下的階段,必将由程式員來主導,甚至比以往更甚。