Golang 接口类型

接口

多态是指代码可以根据类型的具体实现采取不同的行为

实现

接口是用来定义行为的类型。所定义的行为不由接口直接实现,而是通过自定义类型的方法来实现。

接口内部布局:
Golang 接口类型

方法集

方法集定义了接口的接收规则,是有接收者的函数。方法集定义了一组关联到给定类型(struct)的实例类型所对应的方法。(类似与java中new出来的对象)

// I 定义接口,仅仅是方法的集合
type I interface {
	Get() int
	Put(v int)
}
// S 定义了一个类型
type S struct{
	i int
}
// Get 定义类型所拥有的方法
func (p *S) Get() int{
	return p.i
}
// Put
func (p *S) Put(v int){
	p.i = v
}
// 定义通用的调用方法
func f(p I){
	fmt.Println(p.Get())
	p.Put(1)
}

func main(){
	s := S{
		i: 1
	}
	f(s)  // 无法编译通过
	/**
		/listing36.go:32: 不能将 u(类型是 user)作为 sendNotification 的参数类型 notifier:
		user 类型并没有实现 notifier(notify 方法使用指针接收者声明)
	*/
	f(&s) //可以编译通过

对于错误:notify method has pointer receiver
由于接口方法集定义了一组关联到给定类型的值或者指针函数接收者(方法),定义方法时使用的接收者的类型(值或者指针)决定了这个方法是关联到值,还是关联到方法,还是两个都关联。
Go语言定义方法集规则
从实例类型值所绑定的方法集来看,有没有实现接口的方法。

Values Methods Receivers
T (t T)
*T (t T) & (t *T)
  1. T类型值的方法集只包含值接收者声明的方法
  2. T类型指针的方法集既包括值接收者和指针接收者所声明的方法

从接收者类型角度来看某个实例类型值(值或者指针)所对应的方法集(看有没有方法实现了接口):

Methods Receivers Values
(t T) T & *T
(t *T) *T
  1. 如果使用指针接收者来实现一个接口,那么只有指向那个类型的指针才能被interface接收
  2. 如果使用值接收者来实现一个接口,那么那个类型的值和指针都能被interface接收

多态

// 这个示例程序使用接口展示多态行为
02 package main
03
04 import (
05 		"fmt"
06 )
0708 // notifier 是一个定义了
09 // 通知类行为的接口
10 type notifier interface {
11 		notify()
12 }
13
14 // user 在程序里定义一个用户类型
15 type user struct {
16 		name string
17 		email string
18 }
19
20 // notify 使用指针接收者实现了 notifier 接口
21 func (u *user) notify() {
22 		fmt.Printf("Sending user email to %s<%s>\n",
23 		u.name,
24 		u.email)
25 }
26
27 // admin 定义了程序里的管理员
28 type admin struct {
29 		name string
30 		email string
31 }
32
33 // notify 使用指针接收者实现了 notifier 接口
34 func (a *admin) notify() {
35 		fmt.Printf("Sending admin email to %s<%s>\n",
36 		a.name,
37 		a.email)
38 }
39
40 // main 是应用程序的入口
41 func main() {
42 		// 创建一个 user 值并传给 sendNotification
43 		bill := user{"Bill", "bill@email.com"}
44 		sendNotification(&bill)
45
46 		// 创建一个 admin 值并传给 sendNotification
47 		lisa := admin{"Lisa", "lisa@email.com"}
48 		sendNotification(&lisa)
49 }
50
51 // sendNotification 接受一个实现了 notifier 接口的值
52 // 并发送通知
53 func sendNotification(n notifier) {
54 		n.notify()
55 }

最后,可以在代码清单 5-49 中看到这种多态的行为。 main 函数的第 43 行创建了一个 user类型的值,并在第 44 行将该值的地址传给了 sendNotification 函数。这最终会导致执行 user类型声明的 notify 方法。之后,在第 47 行和第 48 行,我们对 admin 类型的值做了同样的事情。最终,因为 sendNotification 接受 notifier 类型的接口值,所以这个函数可以同时执行 user 和 admin 实现的行为。

上一篇:在Linux驱动中使用notifier通知链


下一篇:asd