interface作爲struct field,談談golang結構體中的匿名接口

golang中通過組合(composite)實現類似繼承(extends)和重寫(override)的功能,大家可能平時用的比較多的是struct中匿名struct的寫法,有沒有見過struct中匿名接口(anonymous interface)的寫法呢?

Interface這個接口直接作爲struct中的一個匿名字段,在標準庫sort包中就有這種寫法,:

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

type reverse struct {
    Interface
}

下面我們來看一個完整的例子,以下代碼是從sort包提取出來的:

package main

import (
    "fmt"
)

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

// Array 實現Interface接口
type Array []int

func (arr Array) Len() int {
    return len(arr)
}

func (arr Array) Less(i, j int) bool {
    return arr[i] < arr[j]
}

func (arr Array) Swap(i, j int) {
    arr[i], arr[j] = arr[j], arr[i]
}

// 匿名接口(anonymous interface)
type reverse struct {
    Interface
}

// 重寫(override)
func (r reverse) Less(i, j int) bool {
    return r.Interface.Less(j, i)
}

// 構造reverse Interface
func Reverse(data Interface) Interface {
    return &reverse{data}
}

func main() {
    arr := Array{1, 2, 3}
    rarr := Reverse(arr)
    fmt.Println(arr.Less(0,1))
    fmt.Println(rarr.Less(0,1))
}

sort包中這麼寫的目的是爲了重寫Interface的Less方法,並有效利用了原始的Less方法;通過Reverse可以從Interface構造出一個反向的Interface。go語言利用組合的特性,寥寥幾行代碼就實現了重寫。

對比一下傳統的組合匿名結構體實現重寫的寫法,或許可以更好的幫助我們瞭解匿名接口的優點:

package main

import (
    "fmt"
)

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

type Array []int

func (arr Array) Len() int {
    return len(arr)
}

func (arr Array) Less(i, j int) bool {
    return arr[i] < arr[j]
}

func (arr Array) Swap(i, j int) {
    arr[i], arr[j] = arr[j], arr[i]
}

// 匿名struct
type reverse struct {
    Array
}

// 重寫
func (r reverse) Less(i, j int) bool {
    return r.Array.Less(j, i)
}

// 構造reverse Interface
func Reverse(data Array) Interface {
    return &reverse{data}
}

func main() {
    arr := Array{1, 2, 3}
    rarr := Reverse(arr)
    fmt.Println(arr.Less(0, 1))
    fmt.Println(rarr.Less(0, 1))
}

上面這個例子使用了匿名結構體的寫法,和之前匿名接口的寫法實現了同樣的重寫功能,甚至非常相似。但是仔細對比一下你就會發現匿名接口的優點,匿名接口的方式不依賴具體實現,可以對任意實現了該接口的類型進行重寫。這在寫一些公共庫時會非常有用,如果你經常看一些庫的源碼,匿名接口的寫法應該會很眼熟。

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