Go语言中定时器结束时如何终止函数执行?
Go CLI测验程序问题解决方案
问题根源分析
- fmt.Scanln阻塞无法中断:默认的
fmt.Scanln是阻塞调用,定时器触发后无法强制终止它,导致程序仍等待用户输入。 - 索引越界panic:主逻辑与定时器未同步,在超时触发或题目完成后,仍尝试访问超出题目切片长度的索引。
具体修复方案
1. 解决输入阻塞问题
将输入操作放到独立goroutine中,用channel传递输入结果,通过select同时监听定时器和输入channel,实现超时立即终止输入等待。
2. 解决索引越界问题
在循环中先判断是否还有未完成的题目,确保定时器触发后立即停止所有对题目切片的访问,从根源避免越界。
完整修正代码
package main import ( "fmt" "time" ) func main() { // 示例题目列表,可替换为自定义内容 questions := []string{ "1+1=?", "2+3=?", "5-2=?", } answers := []string{"2", "5", "3"} correctCount := 0 currentQuestionIdx := 0 timer := time.NewTimer(10 * time.Second) // 设置10秒超时时间 defer timer.Stop() fmt.Println("测验开始,你有10秒时间完成所有题目!") for currentQuestionIdx < len(questions) { fmt.Printf("第%d题:%s\n", currentQuestionIdx+1, questions[currentQuestionIdx]) // 启动goroutine处理用户输入,避免阻塞主逻辑 inputChan := make(chan string, 1) go func() { var userInput string fmt.Scanln(&userInput) inputChan <- userInput }() select { case userInput := <-inputChan: // 校验答案并更新计数 if userInput == answers[currentQuestionIdx] { correctCount++ } currentQuestionIdx++ case <-timer.C: fmt.Println("\n时间到!测验结束") goto quizEnd // 直接跳转到结果统计环节 } } quizEnd: fmt.Printf("\n测验完成,你答对了%d/%d道题\n", correctCount, len(questions)) }
关键代码说明
- 输入goroutine:把
fmt.Scanln放到独立goroutine中,用带缓冲的inputChan传递结果,避免goroutine泄漏。 - select分支:同时监听定时器信号和输入结果,超时触发时直接终止循环,不再等待用户输入。
- 索引边界检查:循环条件
currentQuestionIdx < len(questions)确保不会访问超出切片范围的索引,彻底避免越界panic。
内容的提问来源于stack exchange,提问作者avenmia
相关产品推荐
相关产品推荐

