簡體   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