Files
cellbot/plans/go-modernization-plan.md
lafay f3220a2381 refactor: modernize codebase for Go 1.26 and fix adapter issues
- Upgrade Go version from 1.24 to 1.26.1 with updated dependencies
- Replace interface{} with any type throughout codebase
- Add message deduplication in OneBot11 adapter to prevent duplicate event processing
- URL-encode access token in WebSocket connections to handle special characters
- Remove duplicate bot startup hooks in DI providers (now handled by botManager.StartAll)
- Use slices.Clone and errgroup.Go patterns for cleaner concurrent code
- Apply omitzero JSON tags for optional fields (Go 1.24+ feature)
2026-03-18 01:22:49 +08:00

7.5 KiB
Raw Blame History

Go 现代化升级计划

项目概述

  • 项目名称: cellbot
  • 当前 Go 版本: 1.24.0
  • 目标 Go 版本: 1.26.1
  • 分析日期: 2026-03-17

升级摘要

通过代码扫描,识别出以下可使用现代 Go 特性升级的代码点:

升级类型 影响文件数 修改点数 优先级
interface{}any 22 134
omitemptyomitzero 6 32+
wg.Add(1) + goroutine → wg.Go() 2 3
Slice/Map 工具函数优化 多处 若干

详细升级计划

1. 高优先级:interface{} 替换为 any

Go 版本要求: 1.18+

项目中发现 134 处 interface{} 使用,可全部替换为更简洁的 any

涉及文件列表

协议层 (internal/protocol/)
文件 修改点 说明
interface.go 2 接口定义
message.go 5 消息段数据
action.go 4 动作参数
event.go 4 事件数据
bot.go 1 SendAction 返回值
OneBot11 适配器 (internal/adapter/onebot11/)
文件 修改点 说明
types.go 8 类型定义
adapter.go 6 适配器方法
action.go 15 动作构建函数
event.go 14 事件解析
message.go 12 消息转换
client.go 2 HTTP 客户端
Milky 适配器 (internal/adapter/milky/)
文件 修改点 说明
types.go 4 类型定义
adapter.go 4 适配器方法
bot.go 15 Bot 方法
event.go 20+ 事件转换
api_client.go 2 API 客户端
引擎模块 (internal/engine/)
文件 修改点 说明
middleware.go 3 指标数据
plugin.go 4 插件处理
插件模块 (internal/plugins/)
文件 修改点 说明
welcome/welcome.go 4 欢迎消息
mcstatus/mcstatus.go 1 状态命令
mcstatus/ping.go 5 ping 解析

示例修改

// 修改前
func (a *BaseAction) Execute(ctx interface{}) (map[string]interface{}, error)

// 修改后
func (a *BaseAction) Execute(ctx any) (map[string]any, error)

2. 高优先级:omitempty 替换为 omitzero

Go 版本要求: 1.24+

对于 time.Durationtime.Time、结构体、切片、map 类型,应使用 omitzero 替代 omitempty,因为 omitempty 对这些类型不生效。

涉及文件列表

文件 建议修改字段
internal/adapter/onebot11/types.go Duration int64, Interval int64 等数值字段
internal/adapter/onebot11/action.go Duration int64, Delay int 等时长字段
internal/adapter/milky/types.go ExpireTime *int64, ShutUpEndTime *int64 等时间字段
internal/protocol/event.go GroupID string, UserID string 等可选字段

示例修改

// 修改前
type SetGroupBanAction struct {
    GroupID int64 `json:"group_id"`
    Duration int64 `json:"duration,omitempty"` // 0 表示取消禁言
}

// 修改后
type SetGroupBanAction struct {
    GroupID int64 `json:"group_id"`
    Duration int64 `json:"duration,omitzero"` // 0 表示取消禁言
}

3. 中优先级:wg.Go() 替换 wg.Add(1) + goroutine

Go 版本要求: 1.25+

项目中发现 3 处 可使用更简洁的 wg.Go() 模式。

涉及文件

文件 行号 当前代码
internal/engine/scheduler.go 332-333 j.wg.Add(1) + go j.run()
internal/engine/scheduler.go 431-432 j.wg.Add(1) + go j.run()
internal/engine/eventbus.go 66-67 eb.wg.Add(1) + go eb.dispatch()

示例修改

// 修改前 (scheduler.go:332-333)
j.wg.Add(1)
go j.run()

// 修改后
j.wg.Go(j.run)

注意: 需要调整 run() 方法的签名,移除 defer j.wg.Done() 调用。


4. 中优先级:使用 slicesmaps

Go 版本要求: 1.21+

可优化的代码模式

项目中存在一些可以优化的 slice 操作:

文件 当前模式 建议优化
internal/engine/eventbus.go:222-224 手动复制切片 slices.Clone()
internal/engine/dispatcher.go:240-242 手动复制切片 slices.Clone()

示例修改

// 修改前
subsCopy := make([]*Subscription, len(subs))
copy(subsCopy, subs)

// 修改后
subsCopy := slices.Clone(subs)

5. 低优先级:其他现代 Go 特性

5.1 使用 time.Since 替换 time.Now().Sub()

项目已正确使用 time.Since,无需修改。

5.2 使用 min/max 内置函数

项目中未发现明显的 if-else 比较可替换为 min/max

5.3 使用 cmp.Or 替换空值检查

项目中未发现明显的空字符串检查可替换为 cmp.Or


执行计划

阶段 1升级 Go 版本

  1. 更新 go.mod 文件:

    go 1.26.1
    toolchain go1.26.1
    
  2. 运行 go mod tidy 更新依赖

阶段 2高优先级修改

  1. 批量替换 interface{}any134 处)
  2. 更新 omitemptyomitzero32+ 处)

阶段 3中优先级修改

  1. 重构 scheduler.goeventbus.go 使用 wg.Go()
  2. 使用 slices.Clone() 优化切片复制

阶段 4验证

  1. 运行 go build ./... 确保编译通过
  2. 运行 go test ./... 确保测试通过
  3. 运行 go vet ./... 进行静态分析

风险评估

风险 等级 缓解措施
any 替换导致类型推断问题 编译器会捕获所有类型错误
omitzero 行为差异 仔细测试 JSON 序列化/反序列化
wg.Go() API 不兼容 Go 1.25+ 已稳定支持

预期收益

  1. 代码可读性提升anyinterface{} 更简洁
  2. JSON 序列化正确性omitzero 正确处理零值
  3. 并发代码简化wg.Go() 减少样板代码
  4. 性能优化slices.Clone() 可能使用内部优化

总结

本升级计划将项目从 Go 1.24 升级到 Go 1.26.1,并应用现代 Go 语法特性。主要修改集中在:

  1. 134 处 interface{}any 替换
  2. 32+ 处 omitemptyomitzero 更新
  3. 3 处 wg.Go() 简化
  4. 多处 slices.Clone() 优化

建议按阶段逐步实施,每个阶段完成后进行验证,确保代码质量和功能稳定性。