我有一个运行几分钟的功能,我正试图找到一种方法来阻止它使用一个频道.
我想我不能像我在下面的代码那样做,因为我认为select只会stop在default完成之后处理这个案例.
package main
import (
"fmt"
"time"
)
func main() {
stop := make(chan int)
go func() {
for {
select {
case <-stop:
fmt.Println("return")
return
default:
fmt.Println("block")
time.Sleep(5 * time.Second) // simulate a long running function
fmt.Println("unblock")
}
}
}()
time.Sleep(1 * time.Second)
stop <- 1
}
Run Code Online (Sandbox Code Playgroud)
我认为你不能这样做:Go中的goroutines在某种意义上是合作的:直到goroutine 积极地试图弄清楚它是否应该退出,没有办法强迫它这样做.
事实上,我认为这是一个功能,因为如果你可以强行收获一个长期运行的goroutine,你将无法确定它是否干净利落,即正确释放它所获得的所有资源.
所以要么就是这样(例如,如果你的过程想要退出,只需等待那个goroutine完成)或重组它,以便它定期检查是否有信号退出.或者甚至考虑将它执行的任务卸载到外部进程(但请注意,虽然在释放从操作系统获取的资源方面杀死进程是安全的,但对于可能已更新的进程的外部数据而言,这是不安全的 - 比如文件).
我不认为你可以结束一个 goroutine,但你可以切换到另一个 goroutine。您可以通过将函数包装在 goroutine 中来超时函数,该 goroutine 在完成后将数据发送到通道。然后需要选择等待返回的频道或超时的频道。
package main
import (
"fmt"
"time"
)
func waitForMe(){
time.Sleep(time.Second*5)
}
func main(){
c1 := make(chan string, 1)
go func(){
waitForMe()
c1 <- "waitForMe is done"
}()
select {
case res := <-c1:
fmt.Println(res)
case <-time.After(time.Second*2):
fmt.Println("timed out")
}
}
Run Code Online (Sandbox Code Playgroud)
注意:每次通话时间select,time.After()或有阻塞通道,如果可能的话够程切换到下一个可用的goroutine。
这是您的程序发生的情况。
package main
import (
"fmt"
"time"
)
func main() {
stop := make(chan int)
go func() {
fmt.Println("Goroutine B before for loop")
for {
fmt.Println("Goroutine B inside for loop")
select {
case <-stop:
fmt.Println("return")
return
default:
fmt.Println("Goroutine B default case")
fmt.Println("block")
time.Sleep(5 * time.Second) // simulate a long running function
fmt.Println("unblock")
}
}
}()
fmt.Println("Goroutine A before time.Sleep()")
time.Sleep(1 * time.Second)
fmt.Println("Goroutine A after sleep")
stop <- 1
fmt.Println("Goroutine A after stop")
}
Run Code Online (Sandbox Code Playgroud)
Goroutine A before time.Sleep()
Goroutine B before for loop
Goroutine B inside for loop
Goroutine B default case
block
Goroutine A after sleep
unblock
Goroutine B inside for loop
return
Goroutine A after stop
Run Code Online (Sandbox Code Playgroud)
有用的链接:https : //gobyexample.com/timeouts