1.1.1. 一、接口的定义语法:
go语言的接口是interface 类型,可以定义一组方法,但是这些不需要实现。并且 interface 不能包含任何变量。语法如下:
type 接口名 interface {
方法名1 (参数列表) 返回值列表
方法名2 (参数列表) 返回值列表
}
任何自定义数据类型,就可以实现接口。但是某个类型实现了某个接口,是隐式的实现,并不需要特意指出来。只要实现了接口的所有方法,那么这个类型就实现了这个接口。
- 示例如下:
定义一个User 接口,UserImpl 结构体实现了这个接口。Working 函数接收User 接口作为参数。
//定义一个接口,声明了两个没有实现的方法
type User interface {
Add()
Delete()
}
// 定义一个结构体,实现User接口
type UserImpl struct {
}
func (p UserImpl) Add() { //实现Add
fmt.Println("增加。。。")
}
func (p UserImpl) Delete() { //实现Delete
fmt.Println("删除。。。")
}
//定义一个函数,接口类型做参数。实现多肽
func Working(us User) {
us.Add()
us.Delete()
}
func main() {
userImpl := UserImpl{}
//调用方法,传递接口的实现
Working(userImpl)
}
上面例子中:
1、User 接口和它的实现 UserImpl 没有任何的关系,是一个隐式的实现。
2、如果有User2 接口和User 接口一模一样,那UserImpl 也实现了User2 接口。一个struct可以实现无数个接口。
3、结构体必须全部实现接口的方法,才能是这个接口的实现。比如:上面例子中,如果给User 接口增加一个方法,那调用Working函数时编译就会报错。
1.1.2. 二、接口的注意事项。
1、接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量。
//定义一个接口,声明了两个没有实现的方法
type IUser interface {
Add()
}
// 定义一个结构体,实现User接口
type UserImpl struct {
}
func (p UserImpl) Add() { //实现Add
fmt.Println("增加。。。")
}
func main() {
// 声明接口变量,指向实现类型的实例。
var u IUser = UserImpl{}
}
var u IUser = UserImpl{}
这里就是声明接口变量,指向实现类的实例
2、接口中所有的方法都没有方法体,即都是没有实现的方法。
3、在 Golang 中,一个自定义类型需要将某个接口的所有方法都实现,我们才说这个自定义类型实现了该接口。
4、一个自定义类型只有实现了某个接口,才能将该自定义类型的实例(变量)赋给接口类型。
5、任何自定义数据类型,就可以实现接口,不仅仅是结构体类型。(自定义数据类型用 type声明。比如:type MyInt int 就定义了一个MyInt 的数据类型)。实例如下:
//定义一个接口,声明了两个没有实现的方法
type IUser interface {
Add()
}
type MyInt int
func (i MyInt) Add() { //实现Add
fmt.Println("增加。。。")
}
1、自定义了一个数据类型 MyInt 。
2、MyInt 实现了IUser 接口的Add() 方法。所以MyInt 是IUser 接口的实现。
6、一个自定义类型可以实现多个接口。
7、Golang 接口中不能有任何变量。
type IUser interface {
Name string // 编译报错
Add()
}
8、interface 类型默认是一个指针(引用类型),如果没有对 interface 初始化就使用,那么会输出 nil。
type EmptyInterface interface {
}
func main() {
var test EmptyInterface
fmt.Println(test) //<nil>
}
9、空接口 interface{} 没有任何方法,所以所有类型都实现了空接口, 即我们可以把任何一个变量赋给空接口。
实例:接收空接口作为参数,表示接收任意类型参数。
// 接收空接口做参数,表示接收任意类型参数
func test(p interface{}) {
fmt.Println(p)
}
func main() {
test("你好") // 你好
test(123) // 123
}
也可以这样:
type EmptyInterface interface {
}
func test(p EmptyInterface) {
fmt.Println(p)
}
func main() {
test("你好") // 你好
test(123) // 123
}
还可以这样:interface{} 整体作为一个类型。相当于匿名的接口类型。
func main() {
var testInte interface{} = 15
testInte = "你好"
fmt.Println(testInte)
}
1.1.3. 三、接口的继承。
接口的继承和struct的继承类似。在一个接口内,嵌入其他接口即可。
注意:一个接口(比如 C 接口)可以继承多个别的接口(比如 A、B 接口),这时如果要实现 C 接口,也必须将 A、B 接口的方法也全部实现。
继承实例如下:CInterface 接口继承了BInterface接口 和 AInterface接口。
type AInterface interface {
TestA()
}
type BInterface interface {
TestB()
}
type CInterface interface {
AInterface //继承 AInterface 接口
BInterface //继承 BInterface 接口
TestC()
}
1.1.4. 四、指针类型实现接口。
type IUser interface {
Add()
}
type UserImpl struct {
}
// UserImpl的指针类型实现了Add方法
func (p *UserImpl) Add() {
fmt.Println("增加。。。")
}
func main() {
// 这里直接把指针给接口,因为是UserImpl的指针类型实现了IUser接口。
var u IUser = &UserImpl{}
u.Add()
}
说明:这里是UserImpl的指针类型实现了IUser接口。使用的时候直接把指针赋值给接口即可:
var u IUser = &UserImpl{}