接口

1. 接口的基本介绍

用于定义一组方法的集合,接口允许你定义对象的行为,而不必关心对象的具体实现,这有助于实现代码的松耦合和高内聚。

1.1 接口的定义

接口是一组方法签名的集合,任何类型只要实现了这些方法,就隐式地实现了该接口

1
2
3
4
type Shape interface {
Area() float64
Perimeter() float64
}

1.2 接口的实现

在go语言中,一个类型实现某个接口,并不需要显式声明关系。只要一个类型提供了接口所要求的所有方法,该类型就实现了该接口。

Rectangle 类型实现了 Shape 接口,因为它提供了 Area 和 Perimeter 方法。

1
2
3
4
5
6
7
8
9
10
11
type Rectangle struct {
Width, Height float64
}

func (r Rectangle) Area() float64 {
return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}

1.3 使用接口

接口类型的变量可以存储任何实现了该接口的实例。可以通过接口来调用方法,为无需了解具体类型。

1
2
3
4
5
6
7
8
9
func PrintShapeInfo(s Shape) {
fmt.Println("Area:", s.Area())
fmt.Println("Perimeter:", s.Perimeter())
}

func main() {
r := Rectangle{Width: 3, Height: 4}
PrintShapeInfo(r)
}

在上面的例子中,PrintShapeInfo 函数接受一个 Shape 类型的参数,并调用该参数的方法。由于 Rectangle 实现了 Shape 接口,可以将 Rectangle 的实例传递给 PrintShapeInfo。

1.4 空接口

空接口(interface{})不包含任何方法,因此所有类型都实现了空接口。空接口常用于处理任意类型的数据。

1
2
3
4
5
6
7
8
9
func PrintAnything(i interface{}) {
fmt.Println(i)
}

func main() {
PrintAnything(123)
PrintAnything("hello")
PrintAnything(true)
}

1.5 类型断言

类型断言用于将接口类型的变量转换为具体类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func Describe(i interface{}) {
switch v := i.(type) {
case int:
fmt.Println("Integer:", v)
case string:
fmt.Println("String:", v)
default:
fmt.Println("Unknown type")
}
}

func main() {
var i interface{} = "hello"
Describe(i)
}

2. 实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package main

import (
"fmt"
)

// 声明/定义一个接口
type Usb interface {
//声明了两个没有实现的方法
Start()
Stop()
}

type Phone struct {
}

// 让Phone实现Usb接口的方法
func (p Phone) Start() {
fmt.Println("手机开始工作。。。")
}
func (p Phone) Stop() {
fmt.Println("手机停止工作。。。")
}

type Camera struct {
}

// 让Camera实现Usb接口的方法
func (c Camera) Start() {
fmt.Println("相机开始工作~~~。。。")
}
func (c Camera) Stop() {
fmt.Println("相机停止工作。。。")
}

// 计算机
type Computer struct {
}

// 编写一个方法Working 方法,接收一个Usb接口类型变量
// 只要是实现了Usb接口 (所谓实现Usb接口,就是指实现了 Usb接口声明所有方法)
func (c Computer) Working(usb Usb) {

//通过usb接口变量来调用Start和Stop方法
usb.Start()
usb.Stop()
}

func main() {

//测试
//先创建结构体变量
computer := Computer{}
phone := Phone{}
camera := Camera{}

//关键点
computer.Working(phone)
computer.Working(camera)
}

/*
手机开始工作。。。
手机停止工作。。。
相机开始工作~~~。。。
相机停止工作。。。
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
type Speaker interface {
Speak() string
}

type Person struct {
Name string
}

func (p Person) Speak() string {
return "Hello, my name is " + p.Name
}

type Dog struct {
Name string
}

func (d Dog) Speak() string {
return "Woof! My name is " + d.Name
}

func SaySomething(s Speaker) {
fmt.Println(s.Speak())
}

func main() {
p := Person{Name: "John"}
d := Dog{Name: "Rex"}

SaySomething(p)
SaySomething(d)
}

/*
Hello, my name is John
Woof! My name is Rex
*/

在这个例子中,Person 和 Dog 类型都实现了 Speaker 接口,因为它们都提供了 Speak 方法。SaySomething 函数可以接受任何实现了 Speaker 接口的实例,并调用其 Speak 方法。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!