## 定義
interface是一組method的組合,我們通過interface來定義對象的一組行為。
接口聲明形式:
```
type 接口類型名 interface{
方法名1( 參數列表1 ) 返回值列表1
方法名2( 參數列表2 ) 返回值列表2
…
}
```
- 接口類型名:使用 type 將接口定義為自定義的類型名。Go語言的接口在命名時,一般會在單詞后面添加 er,如有寫操作的接口叫 Writer,有字符串功能的接口叫 Stringer,有關閉功能的接口叫 Closer 等。
- 方法名:當方法名首字母是大寫時,且這個接口類型名首字母也是大寫時,這個方法可以被接口所在的包(package)之外的代碼訪問。
- 參數列表、返回值列表:參數列表和返回值列表中的參數變量名可以被忽略,例如:
```
type writer interface{
Write([]byte) error
}
```
## 實現
接口定義后,需要實現接口,調用方才能正確編譯通過并使用接口。接口的實現需要遵循兩條規則才能讓接口可用。
**接口被實現的條件一:接口的方法與實現接口的類型方法格式一致**
在類型中添加與接口簽名一致的方法就可以實現該方法。簽名包括方法中的名稱、參數列表、返回參數列表。也就是說,只要實現接口類型中的方法的名稱、參數列表、返回參數列表中的任意一項與接口要實現的方法不一致,那么接口的這個方法就不會被實現。
```
package main
import (
"fmt"
)
// 定義一個數據寫入器
type DataWriter interface {
WriteData(data interface{}) error
}
// 定義文件結構,用于實現DataWriter
type file struct {
}
// 實現DataWriter接口的WriteData方法
func (d *file) WriteData(data interface{}) error {
// 模擬寫入數據
fmt.Println("WriteData:", data)
return nil
}
func main() {
// 實例化file
f := new(file)
// 聲明一個DataWriter的接口
var writer DataWriter
// 將接口賦值f,也就是*file類型
writer = f
// 使用DataWriter接口進行數據寫入
writer.WriteData("data")
}
```
**接口被實現的條件二:接口中所有方法均被實現**
當一個接口中有多個方法時,只有這些方法都被實現了,接口才能被正確編譯并使用。
為 DataWriter中 添加一個方法:
```
// 定義一個數據寫入器
type DataWriter interface {
WriteData(data interface{}) error
// 能否寫入
CanWrite() bool
}
```
編譯報錯
```
cannot use f (type *file) as type DataWriter in assignment:
*file does not implement DataWriter (missing CanWrite method)
```
需要在 file 中實現 CanWrite() 方法才能正常使用 DataWriter()。
一個接口的方法,不一定需要由一個類型完全實現,接口的方法可以通過在類型中嵌入其他類型或者結構體來實現。也就是說,使用者并不關心某個接口的方法是通過一個類型完全實現的,還是通過多個結構嵌入到一個結構體中拼湊起來共同實現的。
```
// 一個服務需要滿足能夠開啟和寫日志的功能
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() {
}
```