Wails2 系列 01:从单文件 Wails 到分层项目
cbowen

适合读者

适合已经能创建基础 Wails2 项目,并开始感觉 main.go、Go 方法和前端页面越来越难维护的开发者。

问题场景

很多 Wails2 项目一开始都很轻:一个入口文件、一个 App 结构体、几个暴露给前端的方法,再配一个前端页面。这个阶段很舒服,因为所有东西都能快速找到。

问题通常从功能变多开始:设置、登录、待办、通知、文件导入导出、自动更新、托盘、跨平台差异陆续出现。你可能还没有意识到项目变复杂,但 App 已经开始承担太多职责:它既像应用入口,又像业务服务,还像配置管理器、存储层和系统能力封装。

Wails 项目的结构清晰度,往往不是从“多写几个文件夹”开始的,而是从识别边界开始的。

项目观察

flow-go 的目录作为结构观察对象,可以看到一个真实 Wails2 项目至少有这些边界:

  • main.go:负责 Wails 应用装配、窗口配置、生命周期和服务绑定。
  • internal/service:放置暴露给前端调用的后端业务服务。
  • internal/storageinternal/config:分别处理业务数据持久化和应用配置。
  • frontend/src/servicesfrontend/src/storefrontend/src/pages:把前端调用、状态和页面拆开。
  • frontend/wailsjs:Wails 生成的绑定代码,属于基础设施,不适合手动维护。

这不是说每个项目都必须照搬这些目录,而是说明 Wails 项目天然会同时包含“桌面应用壳”“Go 后端”“Web 前端”“系统能力”“构建发布”几种不同关注点。

拆分原则

第一条原则:main.go 只负责装配。它可以知道应用有哪些服务,但不应该知道每个服务内部怎么实现。

第二条原则:Wails 绑定方法按业务域组织。不要把所有可调用方法都放进一个万能 App,否则前端调用会越来越混乱。

第三条原则:前端不要到处直接依赖生成代码。wailsjs 是桥梁,不是业务 API 层。

第四条原则:数据读写和业务流程分离。业务服务表达“做什么”,存储层负责“怎么保存”。

第五条原则:平台差异集中收敛。托盘、开机启动、窗口材质这类能力应尽量被封装在稳定接口后面。

改造示例

一个刚起步的 Wails 项目可能是这样:

1
2
3
4
.
├── main.go
├── app.go
└── frontend/

功能变多后,可以先拆成更清楚的结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.
├── main.go
├── internal/
│ ├── service/
│ │ ├── app/
│ │ ├── settings/
│ │ └── todo/
│ ├── storage/
│ ├── config/
│ └── platform/
└── frontend/
├── src/
│ ├── services/
│ ├── store/
│ ├── pages/
│ └── components/
└── wailsjs/

这个拆法不追求一开始就完美,而是先让职责有地方放。比如一个待办功能可以这样流动:

1
TodoPage -> frontend services/api/todo -> wailsjs -> TodoService -> storage

这条链路的好处是,每一层都知道自己的上游和下游,不需要跨越整个项目去找逻辑。

检查清单

  • main.go 是否主要负责 Wails 配置、生命周期和服务绑定?
  • 业务方法是否已经按领域拆成多个服务?
  • 前端页面是否避免直接散落调用 wailsjs
  • 存储读写是否集中在固定目录或包里?
  • 配置数据和业务数据是否有明确边界?
  • 平台相关代码是否被集中封装?
  • 新增一个功能时,你是否能说清它应该落在哪几个层里?

下一篇

下一篇会聚焦 main.go:如何让它成为一个清爽的应用装配入口,而不是逐渐膨胀成项目里最大的文件。

 评论
评论插件加载失败
正在加载评论插件