Golang 學習——interface 介面學習(一)

相守之路發表於2020-05-05

Golang中介面定義及實現,空介面,介面巢狀學習

Golang中,介面是一組方法簽名。當型別為介面中的所有方法提供定義時,它被稱為實現介面。它與OOP(物件導向程式設計)非常相似。介面指定了型別應該具有的方法,型別決定了如何實現這些方法。

如果某個物件實現了某個介面的所有方法,則此物件就實現了該介面。

1.定義介面

關鍵字interface用來定義介面,語法如下:

type interface_name interface {
   method_name1([args ...arg_type]) [return_type]
   method_name2([args ...arg_type]) [return_type]
   method_name3([args ...arg_type]) [return_type]
   ...
   method_namen([args ...arg_type]) [return_type]
}

一個介面中可以定義多個方法,根據邏輯需要,自定義引數和返回值。

2.實現介面

一個結構體實現了某個介面的所有方法,則此結構體就實現了該介面。

我們定義一個Phone介面,包含兩個方法call()sendMessage()

type Phone interface {
    call()
    seenMessage()
}

宣告結構體,用來實現介面:

type Huawei struct {
    name  string
    price float64
}

type Xiaomi struct {
    name  string
    price float64
}

宣告瞭HuaweiXiaomi兩個結構體,各包含nameprice兩個欄位。

接下來,實現Phone介面,我們先讓Huawei結構體實現該介面所有方法:

func (huawei Huawei) call() {
    fmt.Printf("%s 有打電話功能.....\n", huawei.name)
}

func (huawei Huawei) seenMessage() {
    fmt.Printf("%s 有發簡訊功能.....\n", huawei.name)
}

初始化Huawei結構體,測試介面的方法:

mate30 := Huawei{
    name:  "Mate 30",
    price: 6999,
}
mate30.call()
mate30.seenMessage()

輸出:

Mate 30 有打電話功能.....
Mate 30 有發簡訊功能.....

Huawei結構體實現了Phone介面的所有方法,那就認為,則Huawei結構體實現了Phone介面。

那如何判斷是否實現了該介面,可參考:
Golang學習——如何判斷Golang介面是否實現?

我們具體也操作下,看看Xiaomi結構體若沒有實現Phone介面會發生什麼?

實現Phone介面一個方法:

func (xiaomi Xiaomi) seenMessage() {
    fmt.Printf("%s 只有發簡訊功能.....\n", xiaomi.name)
}

Xiaomi 只實現了 Phone的 發簡訊方法,所以認為 Xiaomi型別未實現了 Phone 介面。我們具體驗證下:

首先初始化Xiaomi結構體,並測試方法

xiaomi9 := Xiaomi{
    name:  "Xiao 9",
    price: 4999,
}
xiaomi9.seenMessage()

輸出:

Xiao 9 只有發簡訊功能.....

seenMessage()方法測試沒問題,我們使用new()函式來測試下Xiaomi結構體是否實現了Phone介面:

var _ Phone = new(Xiaomi)

下圖是我從自己的IDE(Goland)截的圖,為了方便記錄,我將上下文的程式碼專門換行隔開了。

在這裡插入圖片描述

從圖中可以看到,new下方有紅線,滑鼠浮上去會顯示錯誤資訊,大意就是:Xiaomi未實現Phone介面的某些方法,如:call(),因此不能將Xiaomi用作電話型別。

空介面 interface{}
不包含任何的方法,正因為如此,所有的型別都實現了空介面,因此空介面可以儲存任意型別的數值。

fmt包下的Print系列函式,其引數大多是空介面型別,也可以說支援任意型別:

func Print(a ...interface{}) (n int, err error)
func Println(format string, a ...interface{}) (n int, err error)
func Println(a ...interface{}) (n int, err error)

1.例項

我們定義一個空介面練習下:

// 定義一個空介面
type Empyt_interface interface {
}

// 定義一個入參為任意型別的函式
func getInfo(arg Empyt_interface) {
    fmt.Println("getInfo 函式.....", arg)
}
// 也可以寫成如下形式,更推薦
func getInfo2(arg interface{}) {
    fmt.Println("getInfo2 函式.....", arg)
}

Golang很多庫的原始碼都會以空介面作為引數,表示接受任意型別的引數

我們自己也實戰一下:

定義一個值為任意型別的 map

map1 := make(map[string] interface{})
map1["數字"] = 1
map1["字串"] = "字串"
map1["布林"] = false
fmt.Println("map1 ...........", map1)

輸出:

map1 ........... map[字串:字串 布林:false 數字:1]

顧名思義,介面巢狀就是一個介面中包含了其他介面,如果要實現外部介面,那麼就要把內部巢狀的介面對應的所有方法全實現了。

1.例項

我們定義3個介面,其中有一個介面巢狀了另外兩個:

// 定義3個介面
type A interface {
    test1()
}

type B interface {
    test2()
}

// 定義巢狀介面
type C interface {
    A
    B
    test3()
}

接著我們在定義一個結構體,並實現所有方法:

type Person struct {
    //如果想實現介面C,那不止要實現介面C的方法,還要實現介面A,B中的方法
}

func (p Person) test1() {
    fmt.Println("test1 方法................")
}

func (p Person) test2() {
    fmt.Println("test2 方法................")
}

func (p Person) test3() {
    fmt.Println("test3 方法................")
}

初始化結構體,並測試方法:

var person Person = Person{}
// 實現 C 介面的所有方法
person.test1()
person.test2()
person.test3()

輸出:

test1 方法................
test2 方法................
test3 方法................

以上就是Golang介面的基礎學習,總結了介面的定義及實現,空介面和巢狀介面的概念和使用。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章