繁体   English   中英

如何在Golang中使用goroutines从stdin读取?

[英]How to read from stdin with goroutines in Golang?

有问题清单。 我向用户显示一个接一个的问题,然后等待用户的回答。 每个问题都应在几秒钟内得到回答(例如5秒钟)。 如果正确及时地回答了问题,那么用户会得到一些意见。 我的代码如下所示:

 for i := 0; i < len(questions); i++ {
        fmt.Println(questions[i].Text)
        ans := make(chan int)
        go func() {
            fmt.Print("Enter answer ")
            var u int
            fmt.Scanf("%d\n", &u)
            ans <- u
        }()

        select {
        case userAnswer := <-ans:
            if userAnswer == questions[i].Answer {
                points++
            }
        case <-time.After(5 * time.Second):
            fmt.Println("\n Time is over!")
        }
    }

接下来的问题是:如果用户不回答问题,那么他将按预期收到消息“时间结束”。 但是下一个答案将不被处理,用户应再次输入。 看起来像下一个输出:

question with answer  1
Enter answer: 1
1  is right answer
question with answer  2
Enter answer: 2
2  is right answer
question with answer  3
Enter answer: 
 Time is over!
question with answer  4
Enter answer: 4
4
4  is right answer
question with answer  5
Enter answer: 5
5  is right answer

用户没有回答问题3,因此他需要两次回答问题4。 我知道这个问题是因为goroutines和channel。 但是我不明白,为什么没有价值,那是在超时后从stdin中读取,发送到“ ans”频道或从中获取的。

为什么超时后不能正确接收来自通道的值? 我该如何重写代码,以便用户在上一个问题超时后无需重复输入两次?

对不起,英语不好,谢谢您的帮助。

这里发生的是,当您超时时,在上一个goroutine中仍然有一个fmt.Scanf 您还将在每个循环中分配一个新通道。 最终结果意味着来自问题3的扫描得到您的第一个输入4,然后尝试将其推入一个永远不会被读取的通道。 第二次输入4时,它将被新的goroutine读取,然后被推到您希望在其上找到用户输入的通道。

相反,我建议您将用户输入卸载到一个提供单个通道的goroutine中。

func readInput(input chan<- int) {
    for {
        var u int
        _, err := fmt.Scanf("%d\n", &u)
        if err != nil {
            panic(err)
        }
        input <- u
    }
}

然后像这样处理您的问题:

func main() {
    var points int
    userInput := make(chan int)

    go readInput(userInput)

    for i := 0; i < len(questions); i++ {
        fmt.Println(questions[i].Text)
        fmt.Print("Enter answer ")

        select {
        case userAnswer := <-userInput:
            if userAnswer == questions[i].Answer {
                fmt.Println("Correct answer:", userAnswer)
                points++
            } else {
                fmt.Println("Wrong answer")
            }
        case <-time.After(5 * time.Second):
            fmt.Println("\n Time is over!")
        }
    }
}

您可能需要添加一些其他逻辑或处理程序,以在某些时候终止输入读取goroutine,这取决于程序的实际生命周期,但这是另一个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM