首頁  >  文章  >  後端開發  >  Go語言中類型與介面有什麼關係

Go語言中類型與介面有什麼關係

青灯夜游
青灯夜游原創
2023-01-06 19:52:513889瀏覽

在Go語言中,類型和介面之間有一對多和多對一的關係。一個類型可以同時實作多個接口,而接口間彼此獨立,不知道對方的實作。多個類型也可以實現相同的介面:一個介面的方法,不一定需要由一個類型完全實現,介面的方法可以透過在類型中嵌入其他類型或結構體來實現。也就是說,使用者並不關心某個介面的方法是透過一個類型完全實現的,還是透過多個結構嵌入到一個結構體中拼湊起來共同實現的。

Go語言中類型與介面有什麼關係

本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。

Go語言型別與介面的關係

#在Go語言中型別與介面之間有一對多與多對一的關係,以下將列舉出這些常見的概念,以方便讀者理解介面與類型在複雜環境下的實作關係。

一個型別可以實作多個接口

一個型別可以同時實作多個接口,而介接間彼此獨立,不知道對方的實作。

網路上的兩個程式透過一個雙向的通訊連線實現資料的交換,連接的一端稱為一個 Socket。 Socket 能夠同時讀取和寫入數據,這個特性與文件類似。因此,開發中把文件和 Socket 都具備的讀寫特性抽象化為獨立的讀寫器概念。

Socket 和檔案一樣,使用完畢後,也需要對資源進行釋放。

把Socket 能夠寫入資料和需要關閉的特性使用介面來描述,請參考下面的程式碼:

type Socket struct {
}
func (s *Socket) Write(p []byte) (n int, err error) {
    return 0, nil
}
func (s *Socket) Close() error {
    return nil
}

Socket 結構的Write() 方法實作了io.Writer 介面:

type Writer interface {
    Write(p []byte) (n int, err error)
}

同時,Socket 結構也實作了io.Closer 介面:

type Closer interface {
    Close() error
}

使用Socket 實作的Writer 介面的程式碼,無須了解Writer 介面的實作者是否具備Closer 介面的特性。同樣,使用 Closer 接口的程式碼也不知道 Socket 已經實現了 Writer 接口,如下圖所示。

Go語言中類型與介面有什麼關係
圖:介面的使用與實作過程

在程式碼中使用Socket 結構實作的Writer 介面和Closer 介面程式碼如下:

// 使用io.Writer的代码, 并不知道Socket和io.Closer的存在
func usingWriter( writer io.Writer){
    writer.Write( nil )
}
// 使用io.Closer, 并不知道Socket和io.Writer的存在
func usingCloser( closer io.Closer) {
    closer.Close()
}
func main() {
    // 实例化Socket
    s := new(Socket)
    usingWriter(s)
    usingCloser(s)
}

usingWriter () 和usingCloser() 完全獨立,互相不知道對方的存在,也不知道自己使用的介面是Socket 實現的。

多個類型可以實現相同的介面

一個介面的方法,不一定需要由一個類型完全實現,介面的方法可以透過在類型中嵌入其他類型或結構體來實現。也就是說,使用者並不關心某個介面的方法是透過一個類型完全實現的,還是透過多個結構嵌入到一個結構體中拼湊起來共同實現的。

Service 介面定義了兩個方法:一個是開啟服務的方法(Start()),一個是輸出日誌的方法(Log())。使用GameService 結構體來實作Service,GameService 自己的結構只能實作Start() 方法,而Service 介面中的Log() 方法已經被一個能輸出日誌的日誌器(Logger)實作了,無須再進行GameService 封裝,或者重新實現一次。所以,選擇將 Logger 嵌入到 GameService 能最大程度地避免程式碼冗餘,簡化程式碼結構。詳細實作過程如下:

// 一个服务需要满足能够开启和写日志的功能
type Service interface {
    Start()  // 开启服务
    Log(string)  // 日志输出
}
// 日志器
type Logger struct {
}
// 实现Service的Log()方法
func (g *Logger) Log(l string) {
}
// 游戏服务
type GameService struct {
    Logger  // 嵌入日志器
}
// 实现Service的Start()方法
func (g *GameService) Start() {
}

程式碼說明如下:

  • 第 2 行,定義服務接口,一個服務需要實作 Start() 方法和日誌方法。

  • 第 8 行,定義能輸出日誌的日誌器結構。

  • 第 12 行,為 Logger 新增 Log() 方法,同時實作 Service 的 Log() 方法。

  • 第 17 行,定義 GameService 結構。

  • 第 18 行,在 GameService 中嵌入 Logger 日誌器,以實作日誌功能。

  • 第 22 行,GameService 的 Start() 方法實作了 Service 的 Start() 方法。

此時,實例化GameService,並將實例賦給Service,程式碼如下:

var s Service = new(GameService)
s.Start()
s.Log(“hello”)

s 就可以使用Start() 方法和Log() 方法,其中,Start() 由GameService 實現,Log() 方法由Logger 實作。

【相關推薦:Go影片教學程式設計教學

以上是Go語言中類型與介面有什麼關係的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn