## 定义 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() { } ```