使用Golang构建简单的命令行任务管理器
使用Golang构建简单的命令行任务管理器
我决定采用边做边学的方法,构建了一个简单的任务管理器命令行工具。过去我曾用JavaScript构建过类似但更小的东西,现在我很高兴能再次(并且更多地使用Go)实现它。您的反馈将不胜感激。
2 回复
太棒了,Peter… 继续保持出色的工作!!!
更多关于使用Golang构建简单的命令行任务管理器的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个很棒的Go学习项目!你的任务管理器实现了核心功能,代码结构清晰。以下是一些专业点评和改进建议:
代码亮点
- 清晰的模块化结构:将任务管理逻辑分离到
task包中是正确的设计选择 - JSON持久化:使用标准库的
encoding/json处理数据存储很合适 - 简单的命令行界面:通过
flag包处理命令行参数
可改进的方面
1. 并发安全
当前实现不是并发安全的,多个goroutine同时访问任务列表可能导致数据竞争:
// task/task.go 添加互斥锁保护
package task
import (
"sync"
)
type TaskManager struct {
tasks []Task
mu sync.RWMutex
}
func (tm *TaskManager) AddTask(description string) {
tm.mu.Lock()
defer tm.mu.Unlock()
// ... 现有逻辑
}
func (tm *TaskManager) ListTasks() []Task {
tm.mu.RLock()
defer tm.mu.RUnlock()
return tm.tasks
}
2. 错误处理增强
当前错误处理可以更完善:
// main.go 改进错误处理
func main() {
tm, err := task.LoadTasks()
if err != nil {
log.Printf("警告: 无法加载任务文件: %v,使用空任务列表", err)
tm = &task.TaskManager{}
}
// 命令执行后添加错误检查
if err := tm.SaveTasks(); err != nil {
log.Fatalf("保存任务失败: %v", err)
}
}
3. 使用Cobra或urfave/cli改进CLI
对于更复杂的命令行工具,可以考虑使用成熟的CLI库:
// 使用urfave/cli的示例
import "github.com/urfave/cli/v2"
func main() {
app := &cli.App{
Commands: []*cli.Command{
{
Name: "add",
Usage: "添加新任务",
Action: func(c *cli.Context) error {
return tm.AddTask(c.Args().First())
},
},
},
}
app.Run(os.Args)
}
4. 任务过滤和搜索功能
可以添加更多实用功能:
// task/task.go 添加过滤功能
func (tm *TaskManager) FilterTasks(predicate func(Task) bool) []Task {
tm.mu.RLock()
defer tm.mu.RUnlock()
var filtered []Task
for _, t := range tm.tasks {
if predicate(t) {
filtered = append(filtered, t)
}
}
return filtered
}
// 使用示例:查找未完成的任务
pending := tm.FilterTasks(func(t task.Task) bool {
return !t.Completed
})
5. 测试覆盖
添加单元测试确保功能正确性:
// task/task_test.go
func TestTaskManager_AddTask(t *testing.T) {
tm := &TaskManager{}
tm.AddTask("测试任务")
if len(tm.ListTasks()) != 1 {
t.Errorf("期望1个任务,实际得到%d个", len(tm.ListTasks()))
}
}
性能考虑
- 当前每次操作都重写整个JSON文件,对于大量任务可能效率较低
- 可以考虑使用更高效的数据存储格式或数据库
- 添加任务时使用预分配的切片容量减少内存分配
你的项目是学习Go的绝佳实践,继续完善它会让你更深入理解Go的并发模型、错误处理和项目结构设计。

