基础十一《接口》
未完结 后续补充
接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。
接口
本章学习目标
- 了解为什么需要接口以及接口的特点
- 掌握接口的声明和使用
- 掌握接口值的概念
- 掌握空接口的特点及其使用场景
为什么要有接口
快速入门 模拟上述图片中的应用场景
type Usb interface {
Start()
Stop()
}
type Phone struct {
}
type Camera struct {
}
func (p Phone) Start() {
fmt.Println("手机开始工作...")
}
func (p Phone) Stop() {
fmt.Println("手机停止工作...")
}
func (c Camera) Start() {
fmt.Println("相机开始工作...")
}
func (c Camera) Stop() {
fmt.Println("相机停止工作...")
}
// Computer 计算机
type Computer struct {
}
func (c Computer) Working(usb Usb) {
usb.Start()
usb.Stop()
}
func main() {
var c = Computer{}
var p = Phone{}
var ca Camera
co.Working(p)
co.Working(ca)
}
接口的定义
每个接口类型由任意个方法签名组成,接口的定义格式如下:
type 接口类型名 interface{
方法名1( 参数列表1 ) 返回值列表1
方法名2( 参数列表2 ) 返回值列表2
…
}
- 接口类型名:Go语言的接口在命名时,一般会在单词后面添加er,如有写操作的接口叫Writer,有关闭操作的接口叫closer等。接口名最好要能突出该接口的类型含义。
- 方法名:当方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。
- 参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以省略。
注意事项和细节
- 接口本身不能创建实例 但可以指向一个实现了该接口的自定义类型的变量(实例)
type People interface {
Say()
}
type Stu struct {
Name string
}
func (s *Stu) Say() {
fmt.Println(s.Name, "say ...")
}
func main() {
var i People = &Stu{"十二"} // 结构体变量实现了say 实现了接口People
i.Say()
}
- 接口中所有的方法都没有方法体
- 在Golang中 一个自定义类型将某个接口的方法都实现 我们就说该自定义类型实现了该接口
- 只要是自定义类型都可以实现接口 不仅仅是结构体
//自定义一个数据类型
type MyInt int
//实现Say方法
func (m MyInt) Say() {
fmt.Println("say a number-->", m)
}
func main() {
var myint MyInt = 10
//定义一个接口把 myint 赋值给该接口
var i People = myint
i.Say()
}
- 一个自定义类型可以实现多个接口
- Golang接口中不能有任何变量
- interface类型默认是一个指针(引用类型) 如果没有对interface初始化就使用 那么输出nil
- 空接口interfa{}没有任何方法 所以所有类型都实现了空接口 即我们可以把任何变量赋值给空接口
接口的最佳实践
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}
// ByAge implements sort.Interface for []Person based on
// the Age field.
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func main() {
people := []Person{
{"Bob", 31},
{"John", 42},
{"Michael", 17},
{"Jenny", 26},
}
fmt.Println(people)
// There are two ways to sort a slice. First, one can define
// a set of methods for the slice type, as with ByAge, and
// call sort.Sort. In this first example we use that technique.
sort.Sort(ByAge(people))
fmt.Println(people)
// The other way is to use sort.Slice with a custom Less
// function, which can be provided as a closure. In this
// case no methods are needed. (And if they exist, they
// are ignored.) Here we re-sort in reverse order: compare
// the closure with ByAge.Less.
sort.Slice(people, func(i, j int) bool {
return people[i].Age > people[j].Age
})
fmt.Println(people)