接口本身是调用方和实现方均需要遵守的一种协议,大家按照统一的方法命名参数类型和数量来协调逻辑处理的过程。在 Go 语言中,接口是一种类型,可以定义方法集合的契约或规范。它定义了一个对象的行为,而不指定其实现方式。这种设计使得代码更加灵活和可扩展,可以更好地支持抽象化和多态性。在本章的内容中,将详细讲解Go语言接口的知识,为读者不如本书后面知识的学习打下基础。
8.1 接口基础
接口是计算机编程语言中非常重要的一个概念,在本节的内容中,首先简要介绍接口的基础知识,为读者步入本书后面知识的学习打下基础。
8.1.1 接口的作用
接口这一概念在计算机科学中具有非常重要的作用,它可以提供以下几个方面的功能:
- 定义规范:接口可以定义规范,即描述一组必须实现的方法和属性。通过这种方式,接口可以确保类或模块按照指定的方式进行互操作,从而加强代码的可维护性和可扩展性。
- 实现多态:通过接口,不同的对象可以使用相同的方法名称来执行不同的操作。这使得代码更灵活,更易于扩展和修改。例如,如果有一个描述“汽车”的接口,那么不同的汽车(例如轿车、卡车、摩托车等)都可以实现该接口,并使用共同的方法和属性。
- 简化复杂性:通过接口,程序员可以将系统拆分为不同的模块,每个模块负责特定的任务。这种模块化设计可以降低系统的复杂性,并使代码更易于理解和维护。
- 增强代码可读性和可靠性:接口可以提高代码的可读性和可靠性,因为它们使代码更易于理解和测试。接口的使用可以促进良好的编程实践,例如面向对象设计原则中的单一职责原则和依赖倒置原则。
总之,接口是一种非常有用的编程工具,可以提高代码的可维护性、可扩展性和可读性。
8.1.2 Go语言接口介绍
接口是双方约定的一种合作协议。接口实现者不需要关心接口会被怎样使用,调用者也不需要关心接口的实现细节。接口是一种类型,也是一种抽象结构,不会暴露所含数据的格式、类型及结构。
Go语言不是一种 “传统” 的面向对象编程语言:它里面没有类和继承的概念。但是Go语言里有非常灵活的接口概念,通过它可以实现很多面向对象的特性。很多面向对象的语言都有相似的接口概念,但Go语言中接口类型的独特之处在于它是满足隐式实现的。也就是说,我们没有必要对于给定的具体类型定义所有满足的接口类型;简单地拥有一些必需的方法就足够了。这种设计可以让你创建一个新的接口类型满足已经存在的具体类型却不会去改变这些类型的定义;当我们使用的类型来自于不受我们控制的包时这种设计尤其有用。
接口类型是对其它类型行为的抽象和概括;因为接口类型不会和特定的实现细节绑定在一起,通过这种抽象的方式我们可以让我们的函数更加灵活和更具有适应能力。
8.1.3 声明接口
在 Go 语言中,声明接口的语法格式如下:
type interfaceName interface {
method1(param1 type1, ...) (result1 type2, ...)
method2(param1 type1, ...) (result1 type2, ...)
// ...
}
- interfaceName :表示接口的名称;
- method1、method2 :表示接口的方法集合;
- param1、type1 :表示方法参数的名字和类型;
- result1、type2 :表示方法返回值的名字和类型。
例如下面的代码定义一个名为 person 的结构体类型,它包含三个字段:name、age 和 sex。
type person struct {
name string
age int
sex string
}
注意:在Go语言中,接口的方法集合只包含方法签名,不包含实现代码。这些方法的实现由具体的类型来提供,只要该类型实现了所有接口的方法即可。
在Go语言提供的很多包中都有接口,例如包io中提供了接口Writer:
type Writer interface {
Write(p []byte) (n int, err error)
}
上面的接口Writer可以调用方法Write()写入一个字节数组([]byte),返回值告知写入字节数(n int)和可能发生的错误(err error)。
类似的,在Go语言中还有将一个对象以字符串形式展现的接口Stringer,只要实现了这个接口的类型,在调用方法String()时,都可以获得对象对应的字符串。接口Stringer在 fmt 包中定义如下:
type Stringer interface {
String() string
}
接口Stringer在Go语言中的使用频率非常高,功能类似于 Java 或者 C# 语言里的 ToString。Go语言的每个接口中的方法数量不会很多。Go语言希望通过一个接口精准描述它自己的功能,而通过多个接口的嵌入和组合的方式将简单的接口扩展为复杂的接口。
8.1.4 接口成员
在Go语言中,接口成员只包括方法。接口定义了一组方法的集合,而不是字段或属性。这些方法可以没有实现代码(也称为接口中的空接口),或者它们可以在接口的实现中有具体的实现代码。在接口中,每个方法都由方法名称、参数列表和返回值列表组成。例如,一个简单的接口定义可能如下所示:
type MyInterface interface {
Method1(arg1 Type1, arg2 Type2) ReturnType1
Method2(arg3 Type3, arg4 Type4) ReturnType2
}
在上述代码中,接口MyInterface包含两个方法:Method1和Method2。每个方法都有自己的参数类型和返回值类型。
注意:接口本身不是结构体类型,因此不能包含任何字段或属性。它只是一组方法签名的集合,用于描述可用于某种类型的操作。在使用接口时,我们可以将不同类型的对象视为该接口的实现,只要这些对象实现了接口中定义的所有方法。这种方式使得代码更加灵活和可扩展,因为我们可以通过接口来抽象出不同类型的对象,并统一处理它们。