Go Channels - 推送到通道停止执行
Go Channels - Pushing to a channel stops execution
我正在尝试创建一个命令行测验,用户会被问到一个又一个问题,直到他们完成最后一个问题,或者超时。
我想使用频道,这样我就可以学习如何正确使用它们,可以这么说,我遇到了阻碍。
correctAnswersCh 的思路是从 0 开始,每答对一次就加 1。
在我将零输入频道后,测验总是在 quiz() 函数的第 3 行停止。
我在下面添加了一些代码,但完整代码在这里:
https://play.golang.org/p/vzRCTc7MpIK
func main() {
questions, err := getCsvData()
var limit = time.Duration(3)
flag.Parse()
if err != nil {
log.Fatal(err)
}
quizComplete := make(chan bool)
correctAnswersCh := make(chan int)
go quiz(quizComplete, questions, correctAnswersCh)
select {
case <-time.After(limit*time.Second):
fmt.Println("Timed Out")
}
fmt.Printf("Correct Answers: %v\n", <-correctAnswersCh)
}
func quiz(quizComplete chan bool, questions [][]string, correctAnswersCh chan int) {
reader := bufio.NewReader(os.Stdin)
correctAnswersCh <- 0
// execution stops here. 0 is added to correctAnswersCh, then the quiz func stops
for _, question := range questions {
fmt.Print(question[0], "= ")
answer, _ := reader.ReadString('\n')
if strings.TrimSpace(answer) == question[1] {
cA := <-correctAnswersCh
cA++
correctAnswersCh <- cA
}
}
quizComplete <- true
}
您的 correctAnswersCh
频道是无缓冲的,所以在它上面发送任何东西都会阻塞,直到有人从它那里接收。由于您的 main()
函数仅在超时后才从中接收数据,因此在此之前您的应用程序将被阻止。
一个简单的解决方法是为通道提供 1 个缓冲区:
correctAnswersCh := make(chan int, 1)
虽然这是一些奇怪的频道用法。如果您打算创建并发安全计数器,请使用 aotmic 计数器,例如atomic.AddInt32()
. Another option is to use a mutex (sync.Mutex
or sync.RWMutex
) 在多个 goroutines 同时访问时保护资源(变量)。
我正在尝试创建一个命令行测验,用户会被问到一个又一个问题,直到他们完成最后一个问题,或者超时。
我想使用频道,这样我就可以学习如何正确使用它们,可以这么说,我遇到了阻碍。
correctAnswersCh 的思路是从 0 开始,每答对一次就加 1。
在我将零输入频道后,测验总是在 quiz() 函数的第 3 行停止。
我在下面添加了一些代码,但完整代码在这里: https://play.golang.org/p/vzRCTc7MpIK
func main() {
questions, err := getCsvData()
var limit = time.Duration(3)
flag.Parse()
if err != nil {
log.Fatal(err)
}
quizComplete := make(chan bool)
correctAnswersCh := make(chan int)
go quiz(quizComplete, questions, correctAnswersCh)
select {
case <-time.After(limit*time.Second):
fmt.Println("Timed Out")
}
fmt.Printf("Correct Answers: %v\n", <-correctAnswersCh)
}
func quiz(quizComplete chan bool, questions [][]string, correctAnswersCh chan int) {
reader := bufio.NewReader(os.Stdin)
correctAnswersCh <- 0
// execution stops here. 0 is added to correctAnswersCh, then the quiz func stops
for _, question := range questions {
fmt.Print(question[0], "= ")
answer, _ := reader.ReadString('\n')
if strings.TrimSpace(answer) == question[1] {
cA := <-correctAnswersCh
cA++
correctAnswersCh <- cA
}
}
quizComplete <- true
}
您的 correctAnswersCh
频道是无缓冲的,所以在它上面发送任何东西都会阻塞,直到有人从它那里接收。由于您的 main()
函数仅在超时后才从中接收数据,因此在此之前您的应用程序将被阻止。
一个简单的解决方法是为通道提供 1 个缓冲区:
correctAnswersCh := make(chan int, 1)
虽然这是一些奇怪的频道用法。如果您打算创建并发安全计数器,请使用 aotmic 计数器,例如atomic.AddInt32()
. Another option is to use a mutex (sync.Mutex
or sync.RWMutex
) 在多个 goroutines 同时访问时保护资源(变量)。