只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口,不要为了接口而写接口,那样只会增加不必要的抽象,导致不必要的运行时损耗
接口定义
接口类型是一种抽象的类型。它不会暴露出它所代表的对象的内部值的结构和这个对象支持的基础操作的集合;它们只会表现出它们自己的方法
是一组方法的集合
每个接口由数个方法组成,接口定义:
type USB interface {
函数名称 (形参列表) (返回值列表)
函数名称 (形参列表) (返回值列表)
}
Go语言的接口在命名时,一般会在单词后面添加er,如有写操作的接口叫Writer
接口的作用是为类型提供一种标准化的行为,即如果某个类型实现了接口中定义的方法,那么该类型就可以被视为实现了该接口
在这个特定的例子中,接口 Stringer 描述了一个可以返回字符串表示形式的对象。这在很多情况下非常有用,例如在输出格式化或打印时,可以直接使用对象的字符串表示。任何类型,只要实现了 String() 方法并返回一个字符串,就可以被视为实现了 Stringer 接口。当你需要将实现了 Stringer 接口的对象转换为字符串时,可以直接调用该对象的 String() 方法。这种方式使得输出和打印操作更加灵活和自定义
package fmt
// 这个方法名是 String,它没有参数,返回值是一个字符串。接口中只包含方法的签名,而不包含方法的实现
type Stringer interface {
String() string
}
实现接口的条件
一个对象只要全部实现了接口中的方法,那么就实现了这个接口。换句话说,接口就是一个需要实现的方法列表
接口嵌套
接口可以进行嵌套实现,通过大接口包含小接口
// 接口类型可以进行嵌套
//定义总接口
type animal interface {
peo
dog
cat
}
//定义包含的接口
type peo interface {
}
type dog interface {
}
type cat interface {
}
接口类型变量
接口类型变量能够存储所有实现了该接口的实例,即一个类型实现了某个接口的方法,那么就可以将 该类型定义的变量 赋值给那个 接口类型的变量
// Sayer 接口
type Sayer interface {
say()
}
type dog struct {}
type cat struct {}
// dog实现了Sayer接口
func (d dog) say() {
fmt.Println("汪汪汪") // '"':这实际上是 HTML 实体编码,表示双引号字符' " '
}
// cat实现了Sayer接口
func (c cat) say() {
fmt.Println("喵喵喵")
}
func main() {
var x Sayer // 声明一个Sayer类型的变量x
a := cat{} // 实例化一个cat
b := dog{} // 实例化一个dog
x = a // 可以把cat实例直接赋值给x
x.say() // 喵喵喵
x = b // 可以把dog实例直接赋值给x
x.say() // 汪汪汪
}
空接口
空接口是指没有定义任何方法的接口,因此任何类型都实现了空接口
空接口类型的变量可以存储任意类型的变量