Wails2 系列 02:应用入口:让 main.go 只负责装配
适合读者
适合已经在 Wails2 中绑定过 Go 方法,但不确定入口文件应该放多少逻辑的开发者。
问题场景
Wails2 的入口文件很容易变胖。因为所有关键能力看起来都从这里开始:窗口标题、尺寸、前端资源、生命周期、服务绑定、平台选项、启动参数、通知初始化、数据连接。
如果不设边界,main.go 会慢慢塞进业务判断:用户是否登录、设置怎么保存、数据怎么迁移、按钮点击后做什么、某个平台特殊处理什么。短期看很快,长期看每次改功能都要碰入口,风险也越来越高。
更合理的做法是把 main.go 当成 composition root,也就是应用装配根。
项目观察
观察当前项目结构时,可以把 main.go 理解为几个动作的集合:
- 加载配置和内嵌前端资源。
- 创建存储对象和各个后端服务。
- 在
OnStartup中把 Wails context 交给服务。 - 在
Bind中把服务暴露给前端。 - 在
OnShutdown中做资源关闭。
这些动作都属于“把应用组装起来”,而不是具体业务。
拆分原则
入口文件可以知道模块列表,但不要知道模块内部细节。
入口文件适合做这些事:
- 创建依赖,例如配置、存储、服务实例。
- 连接依赖,例如把 storage 传给 service。
- 配置 Wails 应用,例如窗口、资源、生命周期和绑定。
- 做全局启动和关闭流程。
入口文件不适合做这些事:
- 写具体业务规则。
- 直接读写业务数据。
- 直接处理复杂平台差异。
- 承载前端某个页面的流程逻辑。
改造示例
一个容易失控的入口大概会这样:
1 | func main() { |
更清楚的入口应该只保留装配关系:
1 | func main() { |
如果服务需要 Wails context,可以给每个服务提供统一的 Init 方法:
1 | type Service interface { |
启动时做一件事:把 context 分发下去。
1 | func onStartup(ctx context.Context, services []Service) { |
这样入口仍然知道有哪些服务,但业务细节被留在各自服务内部。
检查清单
main.go中是否还能一眼看出应用由哪些服务组成?main.go是否避免出现具体业务规则?- 服务依赖是否通过构造函数传入?
- Wails context 是否只在启动后注入到需要它的对象?
Bind中绑定的是业务域服务,而不是一堆零散函数?- 关闭流程是否集中处理资源释放?
下一篇
下一篇会继续看后端服务层:当多个能力都要暴露给前端时,应该如何按业务域拆分 Wails 绑定服务。
评论
评论插件加载失败
正在加载评论插件