golang轻量级可插拔命令总线实现插件库go-commandbus的使用
Golang轻量级可插拔命令总线实现插件库go-commandbus的使用
简介
go-commandbus是一个轻量级且可插拔的Go语言命令总线实现库。它提供了一种简单的方式来处理应用程序中的命令模式。
安装
使用go get命令安装:
$ go get github.com/lana/go-commandbus
然后在代码中导入:
import "github.com/lana/go-commandbus"
使用示例
下面是一个完整的使用示例,展示了如何定义命令、注册处理器以及执行命令:
package main
import (
"context"
"log"
"os"
"github.com/lana/go-commandbus"
)
// 定义命令结构体
type CreateUser struct {
Name string
}
// 命令处理器函数
func CreateHandler(ctx context.Context, cmd *CreateUser) error {
log.Printf("user %s created", cmd.Name)
return nil
}
func main() {
// 创建命令总线实例
bus := commandbus.New()
// 注册命令处理器
err := bus.Register(&CreateUser{}, CreateHandler)
if err != nil {
log.Println(err)
os.Exit(1)
}
// 执行命令
err = bus.Execute(context.Background(), &CreateUser{"go-commandbus"})
if err != nil {
log.Println(err)
os.Exit(1)
}
}
代码说明
- 定义命令:创建一个结构体来表示命令(如
CreateUser
) - 创建处理器:定义一个函数来处理该命令,函数签名必须是
func(context.Context, *CommandType) error
- 注册处理器:使用
bus.Register()
方法将命令类型与处理器函数关联 - 执行命令:使用
bus.Execute()
方法执行命令,传入上下文和命令实例
错误处理
在执行过程中可能会遇到以下错误:
- 注册时:如果处理器函数签名不正确会返回错误
- 执行时:如果找不到对应的处理器会返回错误
许可证
该项目使用MIT许可证。
更多关于golang轻量级可插拔命令总线实现插件库go-commandbus的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang轻量级可插拔命令总线实现插件库go-commandbus的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Go-CommandBus: 轻量级可插拔命令总线实现
Go-CommandBus 是一个轻量级的命令总线实现,它允许你将命令与处理程序解耦,支持中间件和插件机制。下面我将详细介绍其使用方法和示例代码。
基本概念
命令总线模式包含三个主要部分:
- Command - 包含执行操作所需数据的结构体
- CommandHandler - 处理特定命令的函数
- CommandBus - 负责将命令路由到相应处理程序的中央调度器
安装
go get github.com/vardius/go-commandbus
基本使用示例
package main
import (
"context"
"fmt"
"log"
"github.com/vardius/go-commandbus"
)
// 定义命令
type CreateUserCommand struct {
ID string
Username string
Email string
}
type DeleteUserCommand struct {
ID string
}
func main() {
// 创建命令总线实例
bus := commandbus.New()
// 注册命令处理程序
if err := bus.Register(
"CreateUserCommand", // 命令名称
func(ctx context.Context, command interface{}) error {
// 类型断言获取具体命令
cmd := command.(CreateUserCommand)
fmt.Printf("创建用户: ID=%s, Username=%s, Email=%s\n",
cmd.ID, cmd.Username, cmd.Email)
// 这里可以添加实际业务逻辑
return nil
},
); err != nil {
log.Fatal(err)
}
if err := bus.Register(
"DeleteUserCommand",
func(ctx context.Context, command interface{}) error {
cmd := command.(DeleteUserCommand)
fmt.Printf("删除用户: ID=%s\n", cmd.ID)
return nil
},
); err != nil {
log.Fatal(err)
}
// 发送命令
ctx := context.Background()
// 创建用户命令
if err := bus.Dispatch(ctx, "CreateUserCommand", CreateUserCommand{
ID: "123",
Username: "john_doe",
Email: "john@example.com",
}); err != nil {
log.Fatal(err)
}
// 删除用户命令
if err := bus.Dispatch(ctx, "DeleteUserCommand", DeleteUserCommand{
ID: "123",
}); err != nil {
log.Fatal(err)
}
}
中间件支持
Go-CommandBus 支持中间件,可以在命令处理前后执行额外逻辑:
func loggingMiddleware(next commandbus.HandlerFunc) commandbus.HandlerFunc {
return func(ctx context.Context, command interface{}) error {
// 命令处理前
fmt.Printf("处理命令前: %T\n", command)
// 调用下一个中间件或处理程序
err := next(ctx, command)
// 命令处理后
if err != nil {
fmt.Printf("处理命令出错: %v\n", err)
} else {
fmt.Println("命令处理成功")
}
return err
}
}
func main() {
bus := commandbus.New(
commandbus.WithMiddleware(loggingMiddleware),
)
// 注册处理程序和发送命令的代码同上...
}
插件机制
Go-CommandBus 支持插件机制,可以扩展功能:
type MetricsPlugin struct{}
func (p *MetricsPlugin) OnCommandReceived(ctx context.Context, command interface{}) {
fmt.Println("收到命令:", command)
}
func (p *MetricsPlugin) OnCommandDispatched(ctx context.Context, command interface{}) {
fmt.Println("命令已分发:", command)
}
func (p *MetricsPlugin) OnCommandHandled(ctx context.Context, command interface{}, err error) {
if err != nil {
fmt.Println("命令处理失败:", command, "错误:", err)
} else {
fmt.Println("命令处理成功:", command)
}
}
func main() {
bus := commandbus.New(
commandbus.WithPlugin(&MetricsPlugin{}),
)
// 注册处理程序和发送命令的代码同上...
}
高级特性
1. 并发控制
bus := commandbus.New(
commandbus.WithCommandHandlersPoolSize(10), // 限制并发处理程序数量
)
2. 超时控制
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := bus.Dispatch(ctx, "CreateUserCommand", CreateUserCommand{
ID: "456",
Username: "timeout_test",
Email: "test@example.com",
}); err != nil {
if errors.Is(err, context.DeadlineExceeded) {
fmt.Println("命令处理超时")
} else {
fmt.Println("其他错误:", err)
}
}
最佳实践
-
命令设计:
- 命令应该是简单的数据传输对象(DTO)
- 包含执行操作所需的最小数据集
- 命名以"Command"结尾
-
处理程序设计:
- 每个处理程序只负责一个命令类型
- 保持处理程序简洁,复杂逻辑委托给服务层
-
错误处理:
- 使用自定义错误类型区分不同类型的错误
- 考虑实现重试机制
-
测试:
func TestUserCreation(t *testing.T) { bus := commandbus.New() var called bool bus.Register("CreateUserCommand", func(ctx context.Context, cmd interface{}) error { called = true return nil }) err := bus.Dispatch(context.Background(), "CreateUserCommand", CreateUserCommand{}) if err != nil { t.Fatalf("预期无错误,得到: %v", err) } if !called { t.Error("处理程序未被调用") } }
总结
Go-CommandBus 提供了以下优势:
- 解耦:将命令发送者与处理程序分离
- 可扩展:通过中间件和插件轻松扩展功能
- 可测试:命令和处理程序可以独立测试
- 灵活性:支持同步和异步处理模式
对于需要清晰分离关注点、支持插件架构的Go应用程序,Go-CommandBus是一个轻量级且强大的解决方案。