8. 综合练习:命令行小工具
这是什么:命令行小工具 = 敲一行命令就能用的程序;本章主角是一个带「并发测算」玩法的待办清单(todo)。
为什么用:前七章的变量、struct、接口、错误、并发是散着学的,不拼一次就还是碎片。这一章把它们全拧成一个能跑的小项目——Go 生态的第一块砖。
如何用:照着骨架把 add、list、done 三个命令写出来,再用 goroutine + channel 加上 bench 并发小测。
8.1 功能
go run . add 完成教程写作
go run . list
go run . done 1
go run . bench ← 并发快乐一下
8.2 数据与命令骨架
// main.go
package main
import (
"fmt"
"os"
"strconv"
)
type Task struct {
ID int
Text string
Done bool
}
var tasks []Task
var nextID = 1
func main() {
if len(os.Args) < 2 { // os.Args[0] 是程序名本身
usage()
return
}
switch os.Args[1] {
case "add":
add(os.Args[2])
case "list":
list()
case "done":
id, _ := strconv.Atoi(os.Args[2]) // 字符串转 int
done(id)
case "bench":
bench()
default:
usage()
}
}
func usage() {
fmt.Println("用法: go run . add|list|done <id>|bench")
}
8.3 各命令实现
func add(text string) {
tasks = append(tasks, Task{ID: nextID, Text: text})
nextID++
fmt.Println("已添加:", text)
}
func list() {
for _, t := range tasks {
mark := " "
if t.Done { mark = "✔" }
fmt.Printf("[%s] %d %s\n", mark, t.ID, t.Text)
}
}
func done(id int) {
for i := range tasks {
if tasks[i].ID == id {
tasks[i].Done = true
return
}
}
fmt.Println("未找到任务", id)
}
你会看到:
$ go run . list
[✔] 1 完成教程写作
[ ] 2 复习接口
8.4 bench:并发小测
func bench() {
var wg sync.WaitGroup
results := make(chan int)
for i := 1; i <= 5; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
total := 0
for j := 0; j < n*1_000_000; j++ { total += j }
results <- total
}(i)
}
go func() { wg.Wait(); close(results) }()
for r := range results {
fmt.Println("单线合计:", r)
}
}
运行体验:5 个 goroutine 并行算完,总体耗时 ≈ 最慢一条,而不是 5 倍相加。
8.5 拓展:数据持久化(选做)
用标准库 encoding/json 把 tasks 写进本地文件(JSON 结构直接对上 struct 标签),下次启动读取:
// 保存:os.WriteFile + json.MarshalIndent
// 加载:os.ReadFile + json.Unmarshal(&tasks)
完成后你的 CLI 就有了「真数据」,可以写进简历第一个工具了。
8.6 知识对照表
| 用到 | 学自 |
|---|---|
| struct + 切片 + range | 第 3、5 章 |
| switch 命令分发 | 第 3 章 |
| os.Args / strconv | 第 3、4 章 |
| 多返回值习惯、错误检查 | 第 4、6 章 |
| goroutine + channel + WaitGroup | 第 7 章 |
8.7 小结
恭喜完成 Go 基础全部 8 章!你已经会:
- 写模块化 Go 程序(包、方法、接口)
- 用 error 习惯「直线式」错误流
- 用 goroutine + channel 做并发设计
打个起点——下一课我们用 Gin 把它变成 Web 后端(进入 Go 板块后续)。去 HTML/CSS/JS 修行过的你,转 Go 只是「换一种写法的舞蹈」。
Go 基础完成。下一站回到 Web:开发工具板块总览 🐸