Golang Todo应用采用四层架构(cmd/handler/service/repository),内存map存储起步,RESTful API设计,聚焦MVP功能,强调分层清晰与接口抽象以保障可测性和可扩展性。

用 Golang 开发一个待办事项(Todo)应用,核心不在于炫技,而在于理清数据流、分层清晰、易于扩展。它完全可以作为入门 Web 开发的“Hello World++”项目——有数据存储、API 接口、基础增删改查,还能自然引出测试、中间件、CLI 等进阶话题。
功能设计:从最小可用出发
不必一上来就做用户系统或实时同步。先聚焦 MVP(最小可行产品):
- 添加任务:支持标题、是否完成、可选描述和截止时间
- 查看列表:支持全部/仅未完成/仅已完成三种视图
- 标记完成/取消完成:状态切换,非删除
- 编辑任务:修改标题、描述、截止时间等字段
- 删除任务:软删除(加 deleted_at)或硬删除均可,推荐初期用硬删除简化逻辑
项目结构:按职责分层,不堆在 main.go 里
推荐采用经典四层结构(无需框架,标准库足够):
- cmd/:程序入口,只做初始化(如加载配置、启动 HTTP server)
- internal/handler/:处理 HTTP 请求,解析参数、调用 service、返回 JSON
- internal/service/:业务逻辑层,比如“标记为完成”要校验是否存在、更新时间戳等
- internal/repository/:数据访问层,负责与存储交互。初期可用内存 map 模拟;后续轻松替换为 SQLite 或 PostgreSQL
这样划分后,单元测试可以只 mock repository,service 层完全脱离 HTTP 和数据库,可测性高。
立即学习“go语言免费学习笔记(深入)”;
存储选型:从内存起步,平滑升级
开发阶段用 map[int]*Todo + sync.RWMutex 完全够用,零依赖、启动快、调试直观:
- 用原子整数做自增 ID(
atomic.AddInt64(&nextID, 1)) - 读多写少场景下,
RWMutex比普通Mutex更高效 - 所有 CRUD 操作封装在 repository 接口里,例如:
Save(ctx, todo) error、FindByID(ctx, id int) (*Todo, error)
当需要持久化时,只需实现同一个接口的 SQL 版本(如用 database/sql + sqlite3 驱动),handler 和 service 层代码一行不用改。
API 设计:RESTful 但务实
用标准 HTTP 方法,路径简洁明确:
- GET /api/todos → 获取任务列表(支持 query 参数:?status=completed)
- POST /api/todos → 创建新任务(JSON body)
- GET /api/todos/{id} → 获取单个任务
- PUT /api/todos/{id} → 全量更新(或 PATCH 做局部更新)
- DELETE /api/todos/{id} → 删除任务
错误统一返回 JSON 格式,如 {"error": "todo not found"},状态码匹配语义(404、400、500 等)。别忘了加简单日志中间件,记录请求路径、耗时、状态码。
基本上就这些。Golang 写 Todo 不复杂,但容易忽略分层和接口抽象。把 repository 抽出来、让 service 不依赖具体存储、handler 只管 HTTP —— 这几步走稳了,后面加 JWT 认证、Swagger 文档、Docker 部署,都会顺滑很多。










