1. 接口
在Go语言中接口(interface)是一种类型,一种抽象的类型。
interface是一组method的集合,接口做的事情就像是定义一个协议(规则),只要一台机器有洗衣服和甩干的功能,我就称它为洗衣机。不关心属性(数据),只关心行为(方法)
Go语言提倡面向接口编程。
1.2接口定义
type 接口类型名 interface{
方法名1( 参数列表1 ) 返回值列表1
方法名2( 参数列表2 ) 返回值列表2
…
}
- 接口类型名:使用 type 将接口定义为自定义的类型名。Go语言的接口在命名时,一般会在单词后面添加 er,如有写操作的接口叫 Writer,有字符串功能的接口叫 Stringer,有关闭功能的接口叫 Closer 等。
- 方法名:当方法名首字母是大写时,且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。
- 参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以被忽略
1.3接口实现条件
保持接口内部函数的一致性,只要完全实现,均可以使用
package day10interface
import "fmt"
type FileWriter interface {
// 接收参数为空接口,可以接收任何参数
Write(data interface{}) error
}
// 定义一个文件结构体
type File struct {
}
// 实现DataWriter接口的WriteData方法
// 因为需要改变文件内容所以结构体file使用指针
func (f *File) Write(data interface{}) error {
// 模拟写入
fmt.Println("完成数据写入")
return nil
}
main函数调用day10_interface中定义的接口
package main
import day10interface "go_pric/day10_interface"
func main() {
// 实例化file
f := new(day10interface.File)
// 声明一个Writer接口
var w day10interface.FileWriter
// 将接口赋值f,也就是*file
w = f
// 调用方法
w.Write("data")
}
1.4 类型和接口的关系
一对一
如1.3所示
一对多
一个类型可以同时实现多个接口,而接口间彼此独立,不知道对方的实现。
要不是在同一个包下引用的结构体,变量或者接口,一定要大写首字母
package day10interface
import "fmt"
type Sayer interface {
Say()
}
type Mover interface {
Move()
}
type Dog struct {
Name string
}
func (d Dog) Say() {
fmt.Println("dog is berk" + d.Name)
}
func (d Dog) Move() {
fmt.Println(d.Name + "is moving")
}
package main
import (
day10interface "go_pric/day10_interface"
)
func main() {
// 实例化Mover
var d = day10interface.Dog{Name: "wwww"}
// 声明一个Writer接口
var m day10interface.Mover
var s day10interface.Sayer
// 将接口赋值f,也就是*file
m = d
// 调用方法
m.Move()
s = d
s.Say()
}
多对一
package day10interface
import "fmt"
type Car struct {
Name string
}
type Cat struct {
Name string
}
type Movinger interface {
Move() string
}
// Car 类型实现Move接口
func (c Car) Move() string {
fmt.Println(c.Name)
return c.Name
}
// Cat类型实现Move接口
func (c Cat) Move() string {
fmt.Println(c.Name)
return c.Name
}
package main
import (
day10interface "go_pric/day10_interface"
)
func main() {
// 实例化car
var car day10interface.Car
car.Name = "AITO M7"
// 实例化cat
var cat day10interface.Cat
cat.Name = "Tom"
// 声明一个Movinger接口
var m day10interface.Movinger
// 将接口赋值f,也就是car
m = car
// 调用方法
m.Move()
m = cat
m.Move()
}
可嵌套
package day10interface
import "fmt"
type Sayer interface {
Say()
}
type Mover interface {
Move()
}
// 接口嵌套
type Animal interface {
Sayer
Mover
}
type Dog struct {
Name string
}
// dog类型实现Sayer接口
func (d Dog) Say() {
fmt.Println(d.Name + " is berking ")
}
// dog类型实现Mover接口
func (d Dog) Move() {
fmt.Println(d.Name + " is moving ")
}
package main
import (
day10interface "go_pric/day10_interface"
)
func main() {
var a day10interface.Animal
a = day10interface.Dog{Name: "Jog"}
a.Move()
a.Say()
}
1.5.1 空接口的应用
空接口作为函数的参数可以接收任何类型的数据,特别方便
package day10interface
import "fmt"
// 空接口作为函数参数
func D104(m interface{}) {
fmt.Printf("type: %T value:%v\n", m, m)
// 空接口作为map
// 可以保存任意值的字典
var studentInfo = make(map[string]interface{})
studentInfo["name"] = "lulu"
studentInfo["age"] = 18
studentInfo["num"] = 101
fmt.Println(studentInfo)
}
package main
import (
day10 "go_pric/day10_interface"
"time"
)
func main() {
// 使用匿名函数作为参数传
day10.D104(func() {
go func() {
time.Sleep(time.Second)
}()
})
}