目录
什么是接口
接口本身是调用方和实现方均需要遵守的一种协议,大家按照统一的方法命名参数类型和数量来协调逻辑处理的过程。
Go 语言中使用组合实现对象特性的描述。对象的内部使用结构体内嵌组合对象应该具有的特性,对外通过接口暴露能使用的特性。
Go 语言的接口设计是非侵入式的,接口编写者无须知道接口被哪些类型实现。而接口实现者只需知道实现的是什么样子的接口,但无须指明实现哪一个接口。编译器知道最终编译时使用哪个类型实现哪个接口,或者接口应该由谁来实现。
接口的声明
语法
type 接口类型名 interface{
方法名1(参数列表1) 返回值列表1
方法名n(参数列表n) 返回值列表n
}
说明
接口类型名:使用 type 将接口定义为自定义的类型名。Go语言的接口在命名时,一般会在单词后面添加 er,如有写操作的接口叫 Writer,有字符串功能的接口叫 Stringer,有关闭功能的接口叫 Closer 等。
方法名:当方法名首字母是大写时,且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以省略不写,数据类型要写。
接口的方法:接口的方法在接口中只定义。具体的实现逻辑在结构体中完成。
接口的实现:实现关系在Go语言中是隐式的。两个类型之间的实现关系不需要在代码中显式地表示出来。Go语言中没有类似于 implements 的关键字。 Go编译器将自动在需要的时候检查两个类型之间的实现关系。只要结构体拥有接口里声明的所有方法,就称该结构体"实现了接口"。
接口被实现的条件:
- 接口的方法与实现接口的类型方法格式一致。
- 接口中所有方法均被实现。
示例
// 定义一个接口
type Cruder interface {
selectList(int, int) (int, error)
updateOne(string) (int, error)
}
// 定义一个结构体,结构体实现了接口中的所有方法,那么就表示这个结构体实现了这个接口
// 定义结构体
type Product struct {
id string
name string
producedDate time.Time
}
// 实现方法
func (Product) selectList(pageNum int, pageSize int) (int, error) {
return 1, nil
}
// 实现方法
func (Product) updateOne(id string) (int, error) {
return 1, nil
}
// 使用
func testInter(c Cruder) {
c.selectList(1, 10)
c.updateOne("1")
}
func main() {
var p = Product{}
testInter(p)
}
接口的赋值
// 以上面的示例为例
func main() {
var p Product
var c Cruder
c = p
}
如果 结构体实现的接口方法是指针类型,那么传值的时候就要赋值实例的地址
// 例如这个接口的实现 是 *Product
func (*Product) selectList(pageNum int, pageSize int) (int, error) {
return 1, nil
}
// 赋值
func main() {
var p Product
var c Cruder
c = &p // 赋值的时候就要去实例的地址
}
接口的嵌套
type Cruder interface {
selectList(int, int) (int, error)
updateOne(string) (int, error)
}
type Producter interface {
Cruder // 嵌套其他的接口,表示Producter这个里面也有了Cruder的方法
delete(string) (int, error)
}
空接口
空接口是接口类型的特殊形式,空接口没有任何方法,因此任何类型都无须实现空接口。从实现的角度看,任何值都满足这个接口的需求。因此空接口类型可以保存任何值,也可以从空接口中取出原值。
空接口类型类似于 C# 或 Java 语言中的 Object、C语言中的 void*、C++ 中的 std::any。在泛型和模板出现前,空接口是一种非常灵活的数据抽象保存和使用的方法。
空接口的内部实现保存了对象的类型和指针。使用空接口保存一个数据的过程会比直接用数据对应类型的变量保存稍慢。因此在开发中,应在需要的地方使用空接口,而不是在所有地方使用空接口
空接口的定义使用 interface{}
var i interface{}
示例1
var i interface{}
i = 1
fmt.Println(i) // 1
i = "hello"
fmt.Println(i) // hello
i = false
fmt.Println(i) // false
示例2
func testNilInter(a interface{}) {
fmt.Println(a)
}
func main() {
testNilInter(1)
testNilInter("hello")
testNilInter(false)
}
类型断言
func test1(i interface{}) {
// 判断 i 是否是 int 类型,如果是 ok 为true,把 i 赋值给 v
if v, ok := i.(int); ok {
fmt.Println("int = ", v)
} else if v, ok := i.(float32); ok {
fmt.Println("float32 = ", v)
} else if v, ok := i.(User); ok { // 自定义类型
fmt.Println("User = ", v)
}
}
func main() {
var i User
test(i)
}
func test2(i interface{}) {
switch i.(type) {
case int:
fmt.Println("int = ", i)
case float32:
fmt.Println("float32 = ", i)
case User:
fmt.Println("User = ", i)
}
}
func main() {
var i User
test(i)
}
全套教程地址:Golang全套教程