我这里有一个go例程,需要在上下文到期时从外部go例程中停止该例程。但是,当上下文过期时,go例程不会停止,并且即使控制它的go例程停止也继续进行。
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctxParent := context.Background()
ch := make(chan bool)
d := 5 * time.Second
ctx, cancel := context.WithTimeout(ctxParent, d)
defer cancel()
go doSomething(ctx, ch)
// go func() {
select {
// done
case _ = <-ch:
fmt.Println("goroutine finished")
}
fmt.Println("waiting 11 seconds on main thread, ending all go routines")
time.Sleep(11 * time.Second)
fmt.Println(">>>> END")
}
func doSomething(ctx context.Context, ch chan<- bool) {
// how to kill this go routine if context expires??
go func(ctx context.Context) {
fmt.Println("LOTS OF WORK TIME..")
for i := 0; i < 1000; i++ {
time.Sleep(1 * time.Second) // LOTS OF WORK
fmt.Println(i)
}
}(ctx)
select {
case _ = <-ctx.Done():
fmt.Println("*** Go routine timed out in 5 seconds!!! ****")
ch <- true
return
}
}
这将打印(https://play.golang.org/p/L8u51odiHxS)LOTS OF WORK TIME..
0
1
2
3
4
*** Go routine timed out in 5 seconds!!! ****
goroutine finished
waiting 11 seconds on main thread, ending all go routines
5
6
7
8
9
10
11
12
13
14
15
>>>> END
它不应该打印5,6,7,8 ...等。是否有办法杀死此内部go例程?
最佳答案
您必须在goroutine中检查上下文过期/取消:
go func(ctx context.Context) {
fmt.Println("LOTS OF WORK TIME..")
for i := 0; i < 1000; i++ {
select {
case <-ctx.Done():
return
default:
}
time.Sleep(1 * time.Second) // LOTS OF WORK
fmt.Println(i)
}
}(ctx)
关于go - 从go例程外部停止goroutine,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63713310/