OpenCode 实践课:4 分钟用 Go 写出一个命令行番茄钟计时器

项目介绍

番茄工作法是一种经典的时间管理方法:专注工作 25 分钟,休息 5 分钟,循环往复。今天我们用 OpenCode 在 4 分钟内,用不到 100 行 Go 代码实现一个命令行番茄钟计时器,支持自定义时长、循环轮次,到点自动语音提醒。

技术栈:Go 标准库(flagfmttimeos/exec),零外部依赖。

最终效果:

=== 第 1/4 个番茄钟 ===
工作中... 12:34

准备工作

  • Go 1.18+ 已安装
  • OpenCode 已安装(opencode.ai
  • 终端中进入工作目录,打开 OpenCode

实践过程

步骤一:一句话生成项目骨架

直接告诉 OpenCode 你的需求,它会自动创建整个项目。

我对 OpenCode 说:

> 帮我创建一个 Go 命令行番茄钟计时器项目,名为 pomodoro。支持三个命令行参数:-w 工作时长(默认 25 分钟)、-b 休息时长(默认 5 分钟)、-r 轮次(默认 4)。每轮先工作再休息,最后一轮不休息。倒计时每秒刷新显示。完成后调用系统 TTS 语音播报。

OpenCode 的响应:

OpenCode 先执行 go mod init pomodoro 初始化模块,然后生成 main.go,包括完整的 flag 参数解析、countdown 倒计时函数、notify 语音通知函数。

关键要点:

  • 描述越具体,OpenCode 生成越精准。把参数名、默认值、行为都说清楚。
  • OpenCode 会自动处理模块初始化,无需手动敲 go mod init

步骤二:倒计时核心逻辑

OpenCode 生成的倒计时函数每秒刷新一次,用 \r 回车符原地更新显示,效果丝滑。

func countdown(minutes int, label string) {
	total := minutes * 60
	for remaining := total; remaining >= 0; remaining-- {
		m := remaining / 60
		s := remaining % 60
		fmt.Printf("\r%s中... %02d:%02d", label, m, s)
		time.Sleep(1 * time.Second)
	}
	fmt.Printf("\r%s结束!        \n", label)
}

步骤三:增加系统语音提醒

我希望倒计时结束时有语音提醒,而不是单调的蜂鸣。

我对 OpenCode 说:

> 计时结束后用系统 TTS 播报,Windows 用 PowerShell 的 SpeechSynthesizer,macOS 用 say 命令。

OpenCode 的响应:

func notify(msg string) {
	switch runtime.GOOS {
	case "windows":
		exec.Command("powershell", "-Command",
			"Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('"+msg+"')").Run()
	case "darwin":
		exec.Command("say", msg).Run()
	default:
		fmt.Print("\a") // 其他系统回退到蜂鸣
	}
}

关键要点:

  • 直接告诉 OpenCode 各平台用哪种命令,它会自动按 runtime.GOOS 分平台实现。
  • 这就是 AI 编程助手的优势:你不需要记住那些冗长的 PowerShell 命令。

步骤四:编译运行验证

代码完成后,让 OpenCode 直接编译并试运行。

我对 OpenCode 说:

> 编译并试跑一轮 1 分钟工作的番茄钟。

OpenCode 执行:

go build -o pomodoro.exe && ./pomodoro -w 1 -r 1

控制台出现倒计时,一分钟后听到语音播报"番茄钟完成"——一个完整的番茄钟计时器就做好了。

整个开发过程,用户只需要用自然语言描述需求,OpenCode 负责写代码、编译、调试。从敲下第一行提示词到可运行的程序,不超过 4 分钟。

完整代码

package main

import (
	"flag"
	"fmt"
	"os/exec"
	"runtime"
	"time"
)

func main() {
	workMin := flag.Int("w", 25, "工作时长(分钟)")
	breakMin := flag.Int("b", 5, "休息时长(分钟)")
	rounds := flag.Int("r", 4, "循环轮次")
	flag.Parse()

	for i := 1; i <= *rounds; i++ {
		fmt.Printf("\n=== 第 %d/%d 个番茄钟 ===\n", i, *rounds)
		countdown(*workMin, "工作")
		notify("工作结束,休息一下吧")
		if i < *rounds {
			fmt.Println("\n--- 休息一下 ---")
			countdown(*breakMin, "休息")
			notify("休息结束,开始干活")
		}
	}
	fmt.Println("\n全部番茄钟完成!")
	notify("所有番茄钟已完成")
}

func countdown(minutes int, label string) {
	total := minutes * 60
	for remaining := total; remaining >= 0; remaining-- {
		m := remaining / 60
		s := remaining % 60
		fmt.Printf("\r%s中... %02d:%02d", label, m, s)
		time.Sleep(1 * time.Second)
	}
	fmt.Printf("\r%s结束!        \n", label)
}

func notify(msg string) {
	switch runtime.GOOS {
	case "windows":
		exec.Command("powershell", "-Command",
			"Add-Type -AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('"+msg+"')").Run()
	case "darwin":
		exec.Command("say", msg).Run()
	default:
		fmt.Print("\a")
	}
}

(共 58 行)

小结

用 OpenCode 开发这个番茄钟计时器,全程只说了 3 句话,耗时约 4 分钟。对比传统开发方式——查文档、写代码、调试编译——效率提升至少 5 倍。

OpenCode 的真正价值在于:开发者把精力花在"描述需求"而非"敲代码"上。你只需想清楚要什么,AI 帮你实现细节。跨平台的 PowerShell/Say 兼容、flag 参数绑定这些琐碎语法,都交给 OpenCode 就好。

试试对你自己的项目说一句话,看看 OpenCode 能做到什么程度。