在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 接口,如下圖所示。
圖:介面的使用與實作過程
在程式碼中使用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語言中類型與介面有什麼關係的詳細內容。更多資訊請關注PHP中文網其他相關文章!