Appearance
接口组合
1. 概述
接口组合是 Go 语言中一种强大的特性,它允许通过嵌套其他接口来创建新的接口。这种方式可以实现接口的复用和扩展,使代码更加模块化和可维护。本知识点承接接口定义与实现的概念,为后续的空接口和类型嵌入等内容奠定基础。
2. 基本概念
2.1 语法
接口组合语法
go
// 接口组合
type 新接口名 interface {
接口1
接口2
// ...
额外方法
}
// 示例:组合 Reader 和 Writer 接口
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 组合成 ReadWriter 接口
type ReadWriter interface {
Reader
Writer
}2.2 语义
- 接口组合:通过嵌套多个接口来创建新的接口,新接口包含所有被嵌套接口的方法
- 接口复用:避免重复定义相同的方法集,提高代码的可维护性
- 接口扩展:在组合现有接口的基础上添加新的方法,实现接口的扩展
- 隐式实现:如果一个类型实现了所有被组合接口的方法,那么它也隐式实现了组合后的接口
2.3 规范
- 命名规范:组合接口的名称应该清晰表达其组合的接口功能
- 接口设计:组合接口应该保持简洁,避免过度组合导致接口过大
- 单一职责:每个接口应该专注于单一职责,通过组合实现复杂功能
3. 原理深度解析
3.1 接口组合的底层实现
接口组合在编译时会被展开,组合接口包含所有被嵌套接口的方法。从底层实现来看,组合接口与普通接口没有本质区别,都是方法签名的集合。
3.2 接口组合与类型实现
当一个类型实现了组合接口中所有被嵌套接口的方法时,它就自动实现了组合接口。Go 语言的编译器会检查类型是否实现了组合接口中的所有方法。
3.3 接口组合的继承关系
接口组合不是继承,而是组合关系。组合接口只是包含了其他接口的方法,而不是继承它们的行为。这种组合关系更加灵活,避免了继承带来的问题。
4. 常见错误与踩坑点
4.1 错误表现:接口方法冲突
产生原因:组合的多个接口中存在同名方法,导致方法冲突 解决方案:避免组合具有同名方法的接口,或重新设计接口结构
4.2 错误表现:过度组合导致接口过大
产生原因:组合了过多的接口,导致新接口包含过多方法,违反单一职责原则 解决方案:合理设计接口,保持接口的单一职责,避免过度组合
4.3 错误表现:接口实现不完整
产生原因:类型只实现了组合接口中的部分方法,导致编译错误 解决方案:确保类型实现了组合接口中的所有方法
5. 常见应用场景
5.1 场景描述:标准库中的接口组合
使用方法:Go 标准库中广泛使用接口组合,如 io.ReadWriter、io.ReadCloser 等 示例代码:
go
// 标准库中的接口组合
package io
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}
type ReadCloser interface {
Reader
Closer
}
type WriteCloser interface {
Writer
Closer
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}5.2 场景描述:业务接口组合
使用方法:在业务逻辑中组合多个接口,创建更复杂的接口 示例代码:
go
// 定义基础接口
type Repository interface {
Save(data interface{}) error
Find(id string) (interface{}, error)
}
type Logger interface {
Log(message string)
}
type Validator interface {
Validate(data interface{}) error
}
// 组合接口
type Service interface {
Repository
Logger
Validator
Process(data interface{}) error
}
// 实现组合接口
type UserService struct {
repo Repository
logger Logger
validator Validator
}
func (s *UserService) Save(data interface{}) error {
return s.repo.Save(data)
}
func (s *UserService) Find(id string) (interface{}, error) {
return s.repo.Find(id)
}
func (s *UserService) Log(message string) {
s.logger.Log(message)
}
func (s *UserService) Validate(data interface{}) error {
return s.validator.Validate(data)
}
func (s *UserService) Process(data interface{}) error {
// 处理逻辑
return nil
}5.3 场景描述:插件系统接口
使用方法:通过接口组合定义插件的能力 示例代码:
go
// 定义插件基础接口
type Plugin interface {
Name() string
Initialize() error
}
// 定义可配置插件接口
type Configurable interface {
Configure(config map[string]interface{}) error
}
// 定义可执行插件接口
type Executable interface {
Execute(data interface{}) error
}
// 定义可清理插件接口
type Cleanable interface {
Cleanup() error
}
// 组合接口
type FullPlugin interface {
Plugin
Configurable
Executable
Cleanable
}
// 实现组合接口
type MyPlugin struct {
name string
}
func (p *MyPlugin) Name() string {
return p.name
}
func (p *MyPlugin) Initialize() error {
// 初始化
return nil
}
func (p *MyPlugin) Configure(config map[string]interface{}) error {
// 配置
return nil
}
func (p *MyPlugin) Execute(data interface{}) error {
// 执行
return nil
}
func (p *MyPlugin) Cleanup() error {
// 清理
return nil
}5.4 场景描述:HTTP 处理接口
使用方法:组合多个 HTTP 相关接口,创建完整的 HTTP 处理器 示例代码:
go
// 定义 HTTP 处理接口
type HTTPHandler interface {
ServeHTTP(w http.ResponseWriter, r *http.Request)
}
// 定义中间件接口
type Middleware interface {
Handle(next HTTPHandler) HTTPHandler
}
// 定义路由接口
type Router interface {
Register(path string, handler HTTPHandler)
ServeHTTP(w http.ResponseWriter, r *http.Request)
}
// 定义完整的 HTTP 服务器接口
type HTTPServer interface {
Router
Middleware
Start(addr string) error
Stop() error
}5.5 场景描述:数据访问接口
使用方法:组合多个数据访问相关接口,创建完整的数据访问层 示例代码:
go
// 定义基础数据访问接口
type DataAccess interface {
Connect() error
Disconnect() error
}
// 定义查询接口
type Queryable interface {
Query(sql string, args ...interface{}) (*sql.Rows, error)
}
// 定义执行接口
type Executable interface {
Exec(sql string, args ...interface{}) (sql.Result, error)
}
// 定义事务接口
type Transactional interface {
Begin() (*sql.Tx, error)
}
// 组合接口
type Database interface {
DataAccess
Queryable
Executable
Transactional
}
// 实现组合接口
type MySQLDatabase struct {
db *sql.DB
}
func (m *MySQLDatabase) Connect() error {
// 连接数据库
return nil
}
func (m *MySQLDatabase) Disconnect() error {
return m.db.Close()
}
func (m *MySQLDatabase) Query(sql string, args ...interface{}) (*sql.Rows, error) {
return m.db.Query(sql, args...)
}
func (m *MySQLDatabase) Exec(sql string, args ...interface{}) (sql.Result, error) {
return m.db.Exec(sql, args...)
}
func (m *MySQLDatabase) Begin() (*sql.Tx, error) {
return m.db.Begin()
}6. 企业级进阶应用场景
6.1 场景描述:微服务接口设计
使用方法:通过接口组合定义微服务的能力,实现服务间的解耦 示例代码:
go
// 定义服务基础接口
type Service interface {
HealthCheck() error
Version() string
}
// 定义用户服务接口
type UserService interface {
CreateUser(user User) (string, error)
GetUser(id string) (User, error)
UpdateUser(id string, user User) error
DeleteUser(id string) error
}
// 定义订单服务接口
type OrderService interface {
CreateOrder(order Order) (string, error)
GetOrder(id string) (Order, error)
UpdateOrder(id string, order Order) error
DeleteOrder(id string) error
}
// 组合接口
type ECommerceService interface {
Service
UserService
OrderService
}
// 实现组合接口
type ECommerceServiceImpl struct {
userService UserService
orderService OrderService
}
func (s *ECommerceServiceImpl) HealthCheck() error {
// 健康检查
return nil
}
func (s *ECommerceServiceImpl) Version() string {
return "1.0.0"
}
// 实现 UserService 方法
func (s *ECommerceServiceImpl) CreateUser(user User) (string, error) {
return s.userService.CreateUser(user)
}
func (s *ECommerceServiceImpl) GetUser(id string) (User, error) {
return s.userService.GetUser(id)
}
func (s *ECommerceServiceImpl) UpdateUser(id string, user User) error {
return s.userService.UpdateUser(id, user)
}
func (s *ECommerceServiceImpl) DeleteUser(id string) error {
return s.userService.DeleteUser(id)
}
// 实现 OrderService 方法
func (s *ECommerceServiceImpl) CreateOrder(order Order) (string, error) {
return s.orderService.CreateOrder(order)
}
func (s *ECommerceServiceImpl) GetOrder(id string) (Order, error) {
return s.orderService.GetOrder(id)
}
func (s *ECommerceServiceImpl) UpdateOrder(id string, order Order) error {
return s.orderService.UpdateOrder(id, order)
}
func (s *ECommerceServiceImpl) DeleteOrder(id string) error {
return s.orderService.DeleteOrder(id)
}6.2 场景描述:事件驱动架构接口
使用方法:通过接口组合定义事件处理的能力,实现事件驱动架构 示例代码:
go
// 定义事件接口
type Event interface {
Type() string
Payload() interface{}
}
// 定义事件处理器接口
type EventHandler interface {
Handle(event Event) error
}
// 定义事件发布器接口
type EventPublisher interface {
Publish(event Event) error
}
// 定义事件订阅器接口
type EventSubscriber interface {
Subscribe(eventType string, handler EventHandler) error
Unsubscribe(eventType string, handler EventHandler) error
}
// 组合接口
type EventBus interface {
EventPublisher
EventSubscriber
Start() error
Stop() error
}
// 实现组合接口
type InMemoryEventBus struct {
handlers map[string][]EventHandler
mutex sync.RWMutex
}
func (eb *InMemoryEventBus) Publish(event Event) error {
eb.mutex.RLock()
defer eb.mutex.RUnlock()
if handlers, ok := eb.handlers[event.Type()]; ok {
for _, handler := range handlers {
if err := handler.Handle(event); err != nil {
return err
}
}
}
return nil
}
func (eb *InMemoryEventBus) Subscribe(eventType string, handler EventHandler) error {
eb.mutex.Lock()
defer eb.mutex.Unlock()
if eb.handlers == nil {
eb.handlers = make(map[string][]EventHandler)
}
eb.handlers[eventType] = append(eb.handlers[eventType], handler)
return nil
}
func (eb *InMemoryEventBus) Unsubscribe(eventType string, handler EventHandler) error {
eb.mutex.Lock()
defer eb.mutex.Unlock()
if handlers, ok := eb.handlers[eventType]; ok {
for i, h := range handlers {
if h == handler {
eb.handlers[eventType] = append(handlers[:i], handlers[i+1:]...)
break
}
}
}
return nil
}
func (eb *InMemoryEventBus) Start() error {
// 启动事件总线
return nil
}
func (eb *InMemoryEventBus) Stop() error {
// 停止事件总线
return nil
}7. 行业最佳实践
7.1 实践内容:接口应该小而专一
推荐理由:小接口更容易实现和测试,通过组合可以构建更复杂的接口
7.2 实践内容:合理使用接口组合
推荐理由:接口组合可以实现接口的复用和扩展,避免代码重复
7.3 实践内容:避免方法冲突
推荐理由:组合的接口之间应该避免同名方法,防止方法冲突
7.4 实践内容:接口命名应该清晰表达其功能
推荐理由:清晰的接口命名可以提高代码的可读性和可维护性
8. 常见问题答疑(FAQ)
8.1 问题描述:接口组合与继承有什么区别?
回答内容:接口组合是通过嵌套接口来创建新接口,而继承是通过扩展类来创建新类。接口组合更加灵活,避免了继承带来的问题,如钻石继承等 示例代码:
go
// 接口组合
type ReadWriter interface {
Reader
Writer
}
// 而不是继承
// type ReadWriter extends Reader, Writer {}8.2 问题描述:如何处理接口组合中的方法冲突?
回答内容:避免组合具有同名方法的接口,或重新设计接口结构,将冲突的方法提取到单独的接口中 示例代码:
go
// 避免这种情况
type Interface1 interface {
Method()
}
type Interface2 interface {
Method() // 同名方法
}
// 错误:方法冲突
type BadInterface interface {
Interface1
Interface2
}
// 正确的设计
type MethodInterface interface {
Method()
}
type GoodInterface interface {
MethodInterface
// 其他方法
}8.3 问题描述:接口组合有什么优势?
回答内容:接口组合可以实现接口的复用和扩展,使代码更加模块化和可维护,避免了代码重复 示例代码:
go
// 复用接口
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 扩展接口
type ReadWriter interface {
Reader
Writer
}8.4 问题描述:一个类型需要实现组合接口中的所有方法吗?
回答内容:是的,一个类型需要实现组合接口中所有被嵌套接口的方法,才能说该类型实现了组合接口 示例代码:
go
type ReadWriter interface {
Reader
Writer
}
type MyReaderWriter struct{}
// 必须实现 Reader 和 Writer 的所有方法
func (m *MyReaderWriter) Read(p []byte) (n int, err error) {
// 实现
return 0, nil
}
func (m *MyReaderWriter) Write(p []byte) (n int, err error) {
// 实现
return len(p), nil
}8.5 问题描述:接口组合可以嵌套多层吗?
回答内容:是的,接口组合可以嵌套多层,形成复杂的接口层次结构 示例代码:
go
type A interface {
MethodA()
}
type B interface {
A
MethodB()
}
type C interface {
B
MethodC()
}8.6 问题描述:如何设计良好的接口组合?
回答内容:
- 每个接口应该专注于单一职责
- 接口应该小而简洁
- 避免方法冲突
- 合理命名接口,清晰表达其功能
- 通过组合实现复杂功能,而不是创建过大的接口
9. 实战练习
9.1 基础练习:实现标准库风格的接口组合
解题思路:参考标准库 io 包,实现类似的接口组合 常见误区:方法签名不一致,导致接口实现失败 分步提示:
- 定义 Reader 接口,包含 Read 方法
- 定义 Writer 接口,包含 Write 方法
- 定义 Closer 接口,包含 Close 方法
- 组合这些接口,创建 ReadWriter、ReadCloser、WriteCloser 和 ReadWriteCloser 接口
- 实现一个文件处理器,实现所有接口 参考代码:
go
package main
import (
"fmt"
"io"
"os"
)
// 定义基础接口
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}
type ReadCloser interface {
Reader
Closer
}
type WriteCloser interface {
Writer
Closer
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}
// 实现文件处理器
type FileHandler struct {
file *os.File
}
func NewFileHandler(path string, mode int) (*FileHandler, error) {
file, err := os.OpenFile(path, mode, 0644)
if err != nil {
return nil, err
}
return &FileHandler{file: file}, nil
}
func (fh *FileHandler) Read(p []byte) (n int, err error) {
return fh.file.Read(p)
}
func (fh *FileHandler) Write(p []byte) (n int, err error) {
return fh.file.Write(p)
}
func (fh *FileHandler) Close() error {
return fh.file.Close()
}
func main() {
// 创建文件处理器
fh, err := NewFileHandler("test.txt", os.O_RDWR|os.O_CREATE)
if err != nil {
fmt.Println("创建文件失败:", err)
return
}
defer fh.Close()
// 写入数据
data := []byte("Hello, Interface Composition!")
n, err := fh.Write(data)
if err != nil {
fmt.Println("写入失败:", err)
return
}
fmt.Printf("写入 %d 字节\n", n)
// 读取数据
buffer := make([]byte, 100)
fh.file.Seek(0, io.SeekStart)
n, err = fh.Read(buffer)
if err != nil {
fmt.Println("读取失败:", err)
return
}
fmt.Printf("读取 %d 字节: %s\n", n, string(buffer[:n]))
}9.2 进阶练习:实现业务服务接口组合
解题思路:创建一个业务服务,组合多个功能接口 常见误区:接口设计不合理,导致实现复杂 分步提示:
- 定义 UserRepository 接口,包含用户数据访问方法
- 定义 Logger 接口,包含日志记录方法
- 定义 Validator 接口,包含数据验证方法
- 组合这些接口,创建 UserService 接口
- 实现 UserService 接口 参考代码:
go
package main
import "fmt"
// 定义用户结构
type User struct {
ID string
Name string
Email string
}
// 定义用户仓库接口
type UserRepository interface {
Save(user User) error
FindByID(id string) (User, error)
Update(user User) error
Delete(id string) error
}
// 定义日志接口
type Logger interface {
Info(message string)
Error(message string)
}
// 定义验证接口
type Validator interface {
Validate(user User) error
}
// 组合接口
type UserService interface {
UserRepository
Logger
Validator
Register(user User) error
GetUser(id string) (User, error)
UpdateUser(user User) error
DeleteUser(id string) error
}
// 实现用户仓库
type InMemoryUserRepository struct {
users map[string]User
}
func NewInMemoryUserRepository() *InMemoryUserRepository {
return &InMemoryUserRepository{
users: make(map[string]User),
}
}
func (r *InMemoryUserRepository) Save(user User) error {
r.users[user.ID] = user
return nil
}
func (r *InMemoryUserRepository) FindByID(id string) (User, error) {
user, ok := r.users[id]
if !ok {
return User{}, fmt.Errorf("用户不存在")
}
return user, nil
}
func (r *InMemoryUserRepository) Update(user User) error {
if _, ok := r.users[user.ID]; !ok {
return fmt.Errorf("用户不存在")
}
r.users[user.ID] = user
return nil
}
func (r *InMemoryUserRepository) Delete(id string) error {
if _, ok := r.users[id]; !ok {
return fmt.Errorf("用户不存在")
}
delete(r.users, id)
return nil
}
// 实现日志器
type ConsoleLogger struct{}
func (l *ConsoleLogger) Info(message string) {
fmt.Printf("[INFO] %s\n", message)
}
func (l *ConsoleLogger) Error(message string) {
fmt.Printf("[ERROR] %s\n", message)
}
// 实现验证器
type UserValidator struct{}
func (v *UserValidator) Validate(user User) error {
if user.Name == "" {
return fmt.Errorf("用户名不能为空")
}
if user.Email == "" {
return fmt.Errorf("邮箱不能为空")
}
return nil
}
// 实现用户服务
type UserServiceImpl struct {
repo UserRepository
logger Logger
validator Validator
}
func NewUserService(repo UserRepository, logger Logger, validator Validator) *UserServiceImpl {
return &UserServiceImpl{
repo: repo,
logger: logger,
validator: validator,
}
}
func (s *UserServiceImpl) Save(user User) error {
return s.repo.Save(user)
}
func (s *UserServiceImpl) FindByID(id string) (User, error) {
return s.repo.FindByID(id)
}
func (s *UserServiceImpl) Update(user User) error {
return s.repo.Update(user)
}
func (s *UserServiceImpl) Delete(id string) error {
return s.repo.Delete(id)
}
func (s *UserServiceImpl) Info(message string) {
s.logger.Info(message)
}
func (s *UserServiceImpl) Error(message string) {
s.logger.Error(message)
}
func (s *UserServiceImpl) Validate(user User) error {
return s.validator.Validate(user)
}
func (s *UserServiceImpl) Register(user User) error {
s.Info("注册用户: " + user.Name)
if err := s.Validate(user); err != nil {
s.Error("验证失败: " + err.Error())
return err
}
if err := s.Save(user); err != nil {
s.Error("保存失败: " + err.Error())
return err
}
s.Info("注册成功: " + user.Name)
return nil
}
func (s *UserServiceImpl) GetUser(id string) (User, error) {
s.Info("获取用户: " + id)
user, err := s.FindByID(id)
if err != nil {
s.Error("获取失败: " + err.Error())
return User{}, err
}
return user, nil
}
func (s *UserServiceImpl) UpdateUser(user User) error {
s.Info("更新用户: " + user.ID)
if err := s.Validate(user); err != nil {
s.Error("验证失败: " + err.Error())
return err
}
if err := s.Update(user); err != nil {
s.Error("更新失败: " + err.Error())
return err
}
s.Info("更新成功: " + user.ID)
return nil
}
func (s *UserServiceImpl) DeleteUser(id string) error {
s.Info("删除用户: " + id)
if err := s.Delete(id); err != nil {
s.Error("删除失败: " + err.Error())
return err
}
s.Info("删除成功: " + id)
return nil
}
func main() {
// 创建依赖
repo := NewInMemoryUserRepository()
logger := &ConsoleLogger{}
validator := &UserValidator{}
// 创建服务
service := NewUserService(repo, logger, validator)
// 测试注册
user := User{ID: "1", Name: "Alice", Email: "alice@example.com"}
if err := service.Register(user); err != nil {
fmt.Println("注册失败:", err)
return
}
// 测试获取
user, err := service.GetUser("1")
if err != nil {
fmt.Println("获取失败:", err)
return
}
fmt.Printf("获取用户: %v\n", user)
// 测试更新
user.Email = "alice Updated@example.com"
if err := service.UpdateUser(user); err != nil {
fmt.Println("更新失败:", err)
return
}
// 测试删除
if err := service.DeleteUser("1"); err != nil {
fmt.Println("删除失败:", err)
return
}
}9.3 挑战练习:实现事件总线接口组合
解题思路:创建一个事件总线,组合多个事件相关接口 常见误区:并发安全问题,事件处理顺序问题 分步提示:
- 定义 Event 接口,包含事件类型和负载
- 定义 EventHandler 接口,包含事件处理方法
- 定义 EventPublisher 接口,包含事件发布方法
- 定义 EventSubscriber 接口,包含事件订阅和取消订阅方法
- 组合这些接口,创建 EventBus 接口
- 实现 EventBus 接口,确保并发安全 参考代码:
go
package main
import (
"fmt"
"sync"
)
// 定义事件接口
type Event interface {
Type() string
Payload() interface{}
}
// 实现事件
type SimpleEvent struct {
eventType string
payload interface{}
}
func NewEvent(eventType string, payload interface{}) *SimpleEvent {
return &SimpleEvent{
eventType: eventType,
payload: payload,
}
}
func (e *SimpleEvent) Type() string {
return e.eventType
}
func (e *SimpleEvent) Payload() interface{} {
return e.payload
}
// 定义事件处理器接口
type EventHandler interface {
Handle(event Event) error
}
// 实现事件处理器
type LoggingEventHandler struct{}
func (h *LoggingEventHandler) Handle(event Event) error {
fmt.Printf("处理事件: %s, 负载: %v\n", event.Type(), event.Payload())
return nil
}
// 定义事件发布器接口
type EventPublisher interface {
Publish(event Event) error
}
// 定义事件订阅器接口
type EventSubscriber interface {
Subscribe(eventType string, handler EventHandler) error
Unsubscribe(eventType string, handler EventHandler) error
}
// 组合接口
type EventBus interface {
EventPublisher
EventSubscriber
Start() error
Stop() error
}
// 实现事件总线
type InMemoryEventBus struct {
handlers map[string][]EventHandler
mutex sync.RWMutex
running bool
}
func NewInMemoryEventBus() *InMemoryEventBus {
return &InMemoryEventBus{
handlers: make(map[string][]EventHandler),
running: false,
}
}
func (eb *InMemoryEventBus) Publish(event Event) error {
if !eb.running {
return fmt.Errorf("事件总线未启动")
}
eb.mutex.RLock()
defer eb.mutex.RUnlock()
if handlers, ok := eb.handlers[event.Type()]; ok {
for _, handler := range handlers {
if err := handler.Handle(event); err != nil {
return err
}
}
}
return nil
}
func (eb *InMemoryEventBus) Subscribe(eventType string, handler EventHandler) error {
eb.mutex.Lock()
defer eb.mutex.Unlock()
if eb.handlers == nil {
eb.handlers = make(map[string][]EventHandler)
}
eb.handlers[eventType] = append(eb.handlers[eventType], handler)
return nil
}
func (eb *InMemoryEventBus) Unsubscribe(eventType string, handler EventHandler) error {
eb.mutex.Lock()
defer eb.mutex.Unlock()
if handlers, ok := eb.handlers[eventType]; ok {
for i, h := range handlers {
if h == handler {
eb.handlers[eventType] = append(handlers[:i], handlers[i+1:]...)
break
}
}
}
return nil
}
func (eb *InMemoryEventBus) Start() error {
eb.mutex.Lock()
defer eb.mutex.Unlock()
if eb.running {
return fmt.Errorf("事件总线已启动")
}
eb.running = true
fmt.Println("事件总线启动")
return nil
}
func (eb *InMemoryEventBus) Stop() error {
eb.mutex.Lock()
defer eb.mutex.Unlock()
if !eb.running {
return fmt.Errorf("事件总线未启动")
}
eb.running = false
fmt.Println("事件总线停止")
return nil
}
func main() {
// 创建事件总线
bus := NewInMemoryEventBus()
// 启动事件总线
if err := bus.Start(); err != nil {
fmt.Println("启动失败:", err)
return
}
defer bus.Stop()
// 创建事件处理器
handler := &LoggingEventHandler{}
// 订阅事件
if err := bus.Subscribe("user.created", handler); err != nil {
fmt.Println("订阅失败:", err)
return
}
// 发布事件
event := NewEvent("user.created", map[string]string{"id": "1", "name": "Alice"})
if err := bus.Publish(event); err != nil {
fmt.Println("发布失败:", err)
return
}
// 取消订阅
if err := bus.Unsubscribe("user.created", handler); err != nil {
fmt.Println("取消订阅失败:", err)
return
}
// 再次发布事件(不会被处理)
event2 := NewEvent("user.created", map[string]string{"id": "2", "name": "Bob"})
if err := bus.Publish(event2); err != nil {
fmt.Println("发布失败:", err)
return
}
}10. 知识点总结
10.1 核心要点
- 接口组合是通过嵌套其他接口来创建新接口的特性
- 组合接口包含所有被嵌套接口的方法
- 如果一个类型实现了所有被组合接口的方法,那么它也隐式实现了组合接口
- 接口组合不是继承,而是组合关系,更加灵活
- 接口组合可以实现接口的复用和扩展,使代码更加模块化和可维护
10.2 易错点回顾
- 接口组合中的方法冲突:避免组合具有同名方法的接口
- 过度组合导致接口过大:保持接口的单一职责,避免过度组合
- 接口实现不完整:确保类型实现了组合接口中的所有方法
- 接口命名不清晰:使用清晰的命名表达接口的功能
11. 拓展参考资料
11.1 官方文档链接
11.2 进阶学习路径建议
- 学习空接口的使用
- 深入理解类型断言和类型判断
- 学习类型嵌入和组合
- 探索反射在接口中的应用
本知识点承接《接口定义与实现》,后续延伸至《空接口》,建议学习顺序:接口定义与实现 → 接口组合 → 空接口 → 类型嵌入
