第 4 章:完成核心功能——添加、查看、完成与删除
把四个命令串成完整任务生命周期,并逐个处理空输入、错误编号和不存在任务等边界。
项目路线Go 本地待办清单 CLI4 / 5
一个任务怎样流过四个命令
添加创建事实,查看读取事实,完成修改状态,删除移除事实。四个动作组成最小但完整的生命周期。
实现添加命令
把 add 后面的所有参数重新连接,允许任务标题包含空格;去掉首尾空白后仍为空则拒绝:
title := strings.TrimSpace(strings.Join(arguments, " "))
if title == "" {
return errors.New("任务内容不能为空")
}
task := Task{
ID: nextTaskID(tasks),
Title: title,
CreatedAt: app.Now().UTC(),
}
tasks = append(tasks, task)
只有 Store.Save 成功后才输出“已添加”。不能先告诉用户成功,再发现文件没有写进去。
实现查看命令
for _, task := range tasks {
marker := "[ ]"
if task.Done {
marker = "[x]"
}
fmt.Fprintf(output, "%s #%d %s\n", marker, task.ID, task.Title)
}
空列表不是错误,输出“还没有任务”比什么都不显示更能帮助用户判断程序是否正常运行。
统一解析任务编号
done 和 delete 都需要一个正整数编号,因此抽出共同规则:
func parseTaskID(arguments []string) (int, error) {
if len(arguments) != 1 {
return 0, errors.New("请提供一个任务编号")
}
taskID, err := strconv.Atoi(arguments[0])
if err != nil || taskID < 1 {
return 0, fmt.Errorf("无效任务编号 %q", arguments[0])
}
return taskID, nil
}
格式正确不代表任务存在。遍历结束仍未命中时,应返回 任务 #3 不存在。
完成与删除的差别
完成任务只修改 Done,编号、标题和创建时间保持不变。删除任务则通过切片移除元素:
tasks = append(tasks[:index], tasks[index+1:]...)
删除后不重新编号。稳定 ID 比“列表看起来连续”更重要。
手动跑通生命周期
go run . add 学习 Go 文件操作
go run . add 编写第一个项目测试
go run . list
go run . done 1
go run . delete 2
go run . list
最终应只看到:
[x] #1 学习 Go 文件操作
本章验收
依次尝试空标题、字母编号、负数编号和不存在编号。每次失败都应保留原数据,并给出具体原因。到这里功能已经完成,下一章解决“怎样证明它一直能工作”。
JARVIS · 当前文章
有哪里没看懂?可以只问这篇。
Jarvis 会限定在《第 4 章:完成核心功能——添加、查看、完成与删除》及其公开关联内容中检索,并把引用定位回原文章节。