英文:
How to signal to a goroutine to stop running?
问题
我正在尝试停止一个Go协程,但是我找不到实现这一目标的方法。我在考虑使用第二个通道,但是如果我从那个通道读取数据,它会被阻塞,对吗?下面是一段代码,希望能解释清楚我想要做的事情。
package main
import "fmt"
import "time"
func main() {
var tooLate bool
proCh := make(chan string)
go func() {
for {
fmt.Println("working")
// 如果太晚了,我们停止/返回
if tooLate {
fmt.Println("stopped")
return
}
// 处理一些数据并将结果发送到proCh通道
time.Sleep(2 * time.Second)
proCh <- "processed"
fmt.Println("done here")
}
}()
select {
case proc := <-proCh:
fmt.Println(proc)
case <-time.After(1 * time.Second):
// 以某种方式发送 tooLate <- true
// 这样我们就可以停止运行的Go协程
fmt.Println("too late")
}
time.Sleep(4 * time.Second)
fmt.Println("finish\n")
}
英文:
I'm trying to stop a go routine but I can't find a way to achieve this. I was thinking to use a 2nd channel but if I read from that it would block it isn't it ?. Here is some code which I hope explains what I'm trying to do.
package main
import "fmt"
import "time"
func main() {
var tooLate bool
proCh := make(chan string)
go func() {
for {
fmt.Println("working")
//if is tooLate we stop/return it
if tooLate {
fmt.Println("stopped")
return
}
//processing some data and send the result on proCh
time.Sleep(2 * time.Second)
proCh <- "processed"
fmt.Println("done here")
}
}()
select {
case proc := <-proCh:
fmt.Println(proc)
case <-time.After(1 * time.Second):
// somehow send tooLate <- true
//so that we can stop the go routine running
fmt.Println("too late")
}
time.Sleep(4 * time.Second)
fmt.Println("finish\n")
}
答案1
得分: 2
有几种方法可以实现这个,最简单和最方便的方法是使用另一个通道,例如:
func main() {
tooLate := make(chan struct{})
proCh := make(chan string)
go func() {
for {
fmt.Println("working")
time.Sleep(1 * time.Second)
select {
case <-tooLate:
fmt.Println("stopped")
return
case proCh <- "processed": //这就是为什么它不会阻塞goroutine,如果计时器过期。
default: // 添加default将使其不阻塞
}
fmt.Println("done here")
}
}()
select {
case proc := <-proCh:
fmt.Println(proc)
case <-time.After(1 * time.Second):
fmt.Println("too late")
close(tooLate)
}
time.Sleep(4 * time.Second)
fmt.Println("finish\n")
}
你也可以尝试使用 sync.Cond
。
英文:
There are few ways to achive that, the easiest and most convenient is using another channel like:
func main() {
tooLate := make(chan struct{})
proCh := make(chan string)
go func() {
for {
fmt.Println("working")
time.Sleep(1 * time.Second)
select {
case <-tooLate:
fmt.Println("stopped")
return
case proCh <- "processed": //this why it won't block the goroutine if the timer expirerd.
default: // adding default will make it not block
}
fmt.Println("done here")
}
}()
select {
case proc := <-proCh:
fmt.Println(proc)
case <-time.After(1 * time.Second):
fmt.Println("too late")
close(tooLate)
}
time.Sleep(4 * time.Second)
fmt.Println("finish\n")
}
You can also look into using sync.Cond
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论