用一个现实世界中的例子介绍 Go 接口

假设我现在要用 Go 编写一个 Web 应用。在这个应用里,我要实现给用户发送消息的功能。我可以通过邮件或短信等方式来发送这条消息,这是一个完美的接口使用场景。

在这个虚构的 Web 应用中,先来创建如下 main.go 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

type User struct {
Name string
Email string
}

type UserNotifier interface {
SendMessage(user *User, message string) error
}

func main() {
user := &User{"Panmax", "panmax@email.com"}

fmt.Printf("Welcome %s\n", user.Name)
}

这里的 User 结构体代表一个用户。

可以看到我创建了只有一个函数 SendMessage()UserNotifier 接口。

为了实现这个接口,我需要创建一个结构体来实现 SendMessage() 函数。

1
2
3
4
5
6
7
type EmailNotifier struct {
}

func (notifier EmailNotifier) SendMessage(user *User, message string) error {
_, err := fmt.Printf("Sending email to %s with content %s\n", user.Name, message)
return err
}

正如你看到的,我创建了一个新的 EmailNotifier 结构体。然后我给这个结构体实现了 SendMessage() 方法。在这个例子中,EmailNotifier 只是简单打印了一条消息。在现实世界中你可能需要调用发送邮件的 API,比如 Mailgun

到此,UserNotifier 接口已经实现了,就是这么简单。

下一步要做的是使用 UserNotifier 接口为用户发送一份邮件。

1
2
3
4
5
6
7
8
func main() {
user := User{"Panmax", "panmax@email.com"}
fmt.Printf("Welcome %s\n", user.Name)

var userNotifier UserNotifier
userNotifier = EmailNotifier{}
userNotifier.SendMessage(&user, "Interfaces all the way!")
}

运行这个程序,EmailNotifierSendMessage 方法被正确调用了。

1
2
3
4
go build -o main main.go
./main
Welcome Panmax
Sending email to Panmax with content Interfaces all the way!

下边我们来实现发送短信的接口。

1
2
3
4
5
6
7
type SmsNotifier struct {
}

func (notifier SmsNotifier) SendMessage(user *User, message string) error {
_, err := fmt.Printf("Sending SMS to %s with content %s\n", user.Name, message)
return err
}

我们可以把 Notifier 放进用户结构体中,这样每个用户都有一个属于自己的 Notifier,是不是很酷。

1
2
3
4
5
type User struct {
Name string
Email string
Notifier UserNotifier
}

然后,我们向 User 结构体中添加一个便捷方法 notify(),这个方法使用 UserNotifier 接口给用户发送消息。

1
2
3
func (user *User) notify(message string) error {
return user.Notifier.SendMessage(user, message)
}

最后,我在 main() 函数中创建两个用户,分别调用了它们的 notify() 方法。

1
2
3
4
5
6
7
func main() {
user1 := User{"Dirk", "dirk@email.com", EmailNotifier{}}
user2 := User{"Justin", "bieber@email.com", SmsNotifier{}}

user1.notify("Welcome Email user!")
user2.notify("Welcome SMS user!")
}

最终结果正是我们所预期的:

1
2
3
4
go build -o main main.go
./main
Sending email to Panmax with content Welcome Email user!
Sending SMS to Panmax with content Welcome SMS user!

结语

本文介绍了 Go 接口是如何工作的,同时用一个现实中简单的例子进行了演示。

希望对你有所帮助。