天天看點

Go-接口類型詳解(定義、實作、接口繼承比較等)簡介結構體聲明/定義實作與使用接口和繼承比較注意項全部代碼截圖參考

目錄

簡介

結構體

聲明/定義

實作與使用

實作

多接口實作

接口繼承

空接口

結構體切片排序

接口和繼承比較

注意項

全部代碼

截圖

參考

簡介

Go 語言中的接口是一種内置的類型,它定義了一組方法的簽名,展現了程式設計的高内聚低耦合的特點,本篇文章會介紹接口及基本使用,下篇文章介紹類型斷言。

結構體

定義Monkey結構體,具有climb方法。

type Monkey struct {
	Name string
}

func (m *Monkey)climb(){
	fmt.Println(m.Name,"會爬樹...")
}
           

 定義WuKong結構體,包含Monkey和Tool屬性。

type WuKong struct {
	Monkey
	Tool string
}
           

聲明/定義

定義接口模闆如下:

type interface_name interface {

   method_name1([parameter list]) (return_type)

   method_name2 ([parameter list]) (return_type)

   ...

   method_namen([parameter list]) (return_type)

}

代碼

定義Flyable接口

type Flyable interface {
	Fly()
}
           

實作與使用

實作

實作了接口的所有方法,就是實作了該接口,不需要顯示指明是哪個接口,即隐式實作。

func (w *WuKong) Fly() {
	fmt.Println("筋鬥雲,來...")
}
           

鴨子類型

鴨子類型(duck typing)是動态類型的一種風格,例如,Python語言中比較常見。在這種風格中,一個對象有效的語義,不是由繼承自特定的類或實作特定的接口,而是由"目前方法和屬性集合"決定。

而在Go中,就是由目前結構體的方法集合決定目前結構體是否實作了某個接口。WuKong可以飛,而Monkey不可以飛,WuKong在繼承Monkey的基礎上,擴充了自己的功能。

多接口實作

再定義一個接口

type Swimmable interface {
	Swim()
}
           

實作

func (w *WuKong) Swim()  {
	fmt.Println("老龍王,俺老孫的金箍棒呢?")
}
           

WuKong結構體就實作了上面的兩個接口。

接口繼承

再定義一個接口Skills,繼承前面的兩個接口,并添加新的方法Change

type Skills interface {
	Flyable
	Swimmable
	Change()
}
           

實作

func (w *WuKong) Change()  {
	fmt.Println("看我72變...")
}
           

至此, WuKong結構體實作了四個接口,為什麼是四個呢?因為還有下面這一個

空接口

type Null interface {

}
           

如你所見,什麼方法也沒有,即每個結構體都實作了空接口,都可以指派給空接口,這在排序,後面類型斷言等部分都很有用。

結構體切片排序

func Sort(data Interface)

Sort,本地排序data,無傳回。它調用1次data.Len确定長度,調用O(n*log(n))次data.Less和data.Swap,底層使用的是快排,感興趣的朋友可以看看快排源代碼。本函數不能保證排序的穩定性(即不保證相等元素的相對次序不變)。

// Sort sorts data.
// It makes one call to data.Len to determine n and O(n*log(n)) calls to
// data.Less and data.Swap. The sort is not guaranteed to be stable.
func Sort(data Interface) {
	n := data.Len()
	quickSort(data, 0, n, maxDepth(n))
}
           

Interface接口

type Interface interface {
	// Len is the number of elements in the collection.
	Len() int

        // Less reports whether the element with index i must sort before the element with index j.
	// See Float64Slice.Less for a correct implementation for floating-point values.
	Less(i, j int) bool

	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}
           

 既然這是一個接口,隻要我們實作了Len、Less、Swap方法即可傳參,進行排序。

我們就用Monkey結構體的切片實作一下這個接口。

type MonkeySlice []Monkey
//--------實作Len--------
func (m MonkeySlice) Len() int{
	return len(m)
}
//---------實作Less---------
func (m MonkeySlice) Less(i,j int) bool {
	return m[i].Name < m[j].Name
}
//----------實作Swap---------
func (m MonkeySlice) Swap(i,j int){
	m[i],m[j] = m[j],m[i]
}
           

使用

monkeys := MonkeySlice{{"峨眉猴"},{"齊天大聖"},{"金絲猴"},{"六耳猕猴"},{"孫悟空"}}
	sort.Sort(monkeys)
	fmt.Println(monkeys)
           

接口和繼承比較

  • 當A結構體繼承了B結構體,那麼A結構體就自動的繼承了B結構體的字段和方法,并且可以直接使用
  • 當A結構體需要擴充功能,同時不希望去破壞繼承關系,則可以去實作某個接口即可,
  • 接口是對繼承的補充,是like和is的差別
  • 繼承解決代碼的複用性和可維護性
  • 接口更加靈活,一定程度上實作了解耦

注意項

  • 接口不能建立執行個體,接口可以指向實作了接口的結構體執行個體
  • 結構體必須實作所有接口的方法才可以說實作了該接口
  • 接口預設是指針類型,沒有初始化會輸出nil
  • 空接口可以接收任何類型

全部代碼

package main

import (
	"fmt"
	"sort"
)

type Monkey struct {
	Name string
}

func (m *Monkey)climb(){
	fmt.Println(m.Name,"會爬樹...")
}

//--------Flyable接口---------
type Flyable interface {
	Fly()
}

//--------Swimmable接口-------
type Swimmable interface {
	Swim()
}
//----------接口繼承--------------
type Skills interface {
	Flyable
	Swimmable
	Change()
}
//-----------空接口-----------
type Null interface {

}
//---------不破壞結構體,添加屬性--------
type WuKong struct {
	Monkey
	Tool string
}
//---------不破壞繼承,擴充行為/方法--------
func (w *WuKong) Fly() {
	fmt.Println("筋鬥雲,來...")
}

func (w *WuKong) Swim()  {
	fmt.Println("老龍王,俺老孫的金箍棒呢?")
}

func (w *WuKong) Change()  {
	fmt.Println("看我72變...")
}
type MonkeySlice []Monkey
//--------實作Len--------
func (m MonkeySlice) Len() int{
	return len(m)
}
//---------實作Less---------
func (m MonkeySlice) Less(i,j int) bool {
	return m[i].Name < m[j].Name
}
//----------實作Swap---------
func (m MonkeySlice) Swap(i,j int){
	m[i],m[j] = m[j],m[i]
}

func main() {
	//-----------接口體-------
	w := WuKong{}
	w.Name = "孫悟空"
	//-----------使用方法------
	w.climb()
	//-----------使用實作的接口的方法---------
	w.Fly()
	//-----------結構體指派給接口------------
	var s Skills
	s = &w
	s.Change()
	//----------空接口-------------
	var null Null
	null = w
	wukong := null.(WuKong)
	wukong.Swim()
	//-----------結構體切片排序--------------
	monkeys := MonkeySlice{{"峨眉猴"},{"齊天大聖"},{"金絲猴"},{"六耳猕猴"},{"孫悟空"}}
	sort.Sort(monkeys)
	fmt.Println(monkeys)
}
           

截圖

Go-接口類型詳解(定義、實作、接口繼承比較等)簡介結構體聲明/定義實作與使用接口和繼承比較注意項全部代碼截圖參考

參考

Go标準庫-sort

更多Go相關内容:Go-Golang學習總結筆記

有問題請下方評論,轉載請注明出處,并附有原文連結,謝謝!如有侵權,請及時聯系。如果您感覺有所收獲,自願打賞,可選擇支付寶18833895206(小于),您的支援是我不斷更新的動力。