我是刚开始开发玩具测验 cli 程序。我正在尝试实现一个计时器,以便当计时器结束时,测验就结束了。
这是我的初步实现。
func StartTimer(quizFinished chan bool, timer *time.Timer) {
// Start timer
<-timer.C
fmt.Println("\nQuiz has ended")
quizFinished <- true
return
}
func askQuestions(timer *time.Timer, questions []string, answers []string) []string {
var input string
var userAnswers []string
quizFinished := make(chan bool)
fmt.Println("Starting Quiz...")
go StartTimer(quizFinished, timer)
for index, element := range questions {
select {
case <-quizFinished:
fmt.Println("Quiz has ended")
return userAnswers
default:
fmt.Printf("Question %d: %s? ", index+1, element)
fmt.Scanln(&input)
userAnswers = append(userAnswers, input)
}
}
return userAnswers
}
编辑实现
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
s "strings"
"time"
)
func readFileData(fileName string) (questions []string, answers []string) {
file, err := os.Open(fileName)
if err != nil {
log.Fatalf("failed reading data from file: %v", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
questionAndAnswer := s.Split(scanner.Text(), ",")
question, answer := questionAndAnswer[0], questionAndAnswer[1]
questions = append(questions, question)
answers = append(answers, answer)
}
return questions, answers
}
func askQuestions(timer *time.Timer, questions []string) []string {
var input string
var userAnswers []string = make([]string, 0, len(questions))
quizFinished := make(chan bool, 1)
fmt.Println("Starting Quiz...")
go func() {
<-timer.C
fmt.Println("\nquiz over...")
quizFinished <- true
}()
for index, element := range questions {
fmt.Printf("Question %d: %s? ", index+1, element)
answerCh := make(chan string, 1)
go func() {
fmt.Scanln(&input)
answerCh <- input
}()
select {
case <-quizFinished:
return userAnswers
case answer := <-answerCh:
userAnswers = append(userAnswers, answer)
}
}
return userAnswers
}
func main() {
fileNamePtr := flag.String("filename", "problems.csv", "Specify a file name to read in")
quizTimePtr := flag.Int("time", 5, "Specify how long the quiz should take")
flag.Parse()
timer := time.NewTimer(time.Duration(*quizTimePtr) * time.Second)
questions, answers := readFileData(*fileNamePtr)
// var userAnswers = askQuestions(timer, questions, answers)
var userAnswers = askQuestions(timer, questions)
correctAnswers := 0
incorrectAnswers := 0
for i := 0; i < len(answers); i++ {
if userAnswers[i] == answers[i] {
correctAnswers++
} else {
incorrectAnswers++
}
}
grade := float32(correctAnswers) / float32(len((questions)))
fmt.Printf("Total Questions: %d \n", len(questions))
fmt.Printf("Total Correct Answers: %d \n", correctAnswers)
fmt.Printf("Total Incorrect Answers: %d \n", incorrectAnswers)
fmt.Printf("Grade: %.0f%% \n", grade*100)
}
我不断收到以下输出和错误:
Starting Quiz...
Question 1: 5+5? 10
Question 2: 1+1?
Quiz has ended
2
Returning from quiz...
panic: runtime error: index out of range [2] with length 2
goroutine 1 [running]:
我对通道和 goroutine 的理解还不够深入,还无法理解正在发生的事情。预期的行为是当计时器停止时,它会打印“测验已结束”,并将一个值发送到 quizFinished 通道,该值在 select 语句中读取。我遇到的另一个问题是 Scanln 将在测验结束后等待用户输入。如有任何帮助,我们将不胜感激!
正确答案
当你在主goroutine中调用Scanln
函数时,它会暂停并等待用户输入。即使你的计时器在另一个 Goroutine 中完成并尝试通知主 Goroutine,主 Goroutine 也不会响应,因为它被“Scanner”阻止了。
这就是为什么即使计时器结束,Scanln
仍在等待用户输入。
package main
import (
"fmt"
"time"
)
func askQuestions(timer *time.Timer, questions []string) []string {
var input string
var userAnswers []string
quizFinished := make(chan bool, 1)
fmt.Println("start quiz...")
go func() {
<-timer.C
fmt.Println("\nquiz over...")
quizFinished <- true
}()
for index, element := range questions {
fmt.Printf("question %d: %s? ", index+1, element)
answerCh := make(chan string, 1)
go func() {
fmt.Scanln(&input)
answerCh <- input
}()
select {
case <-quizFinished:
fmt.Println("exit quiz...")
return userAnswers
case answer := <-answerCh:
userAnswers = append(userAnswers, answer)
}
}
return userAnswers
}
func main() {
timer := time.NewTimer(10 * time.Second)
questions := []string{"5+5", "1+1", "8+3"}
responses := askQuestions(timer, questions)
fmt.Println("answer:", responses)
}
以上就是当 go 中计时器完成时如何从函数返回?的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
软考中级精品资料免费领
- 历年真题答案解析
- 备考技巧名师总结
- 高频考点精准押题
- 资料下载
- 历年真题
193.9 KB下载数265
191.63 KB下载数245
143.91 KB下载数1148
183.71 KB下载数642
644.84 KB下载数2756