1、问题引出
现在有个需要,需要关闭以下代码,i=5的,goroutine(看观先想想,自己的实现方法)
package main
import (
"fmt"
"time"
)
func main() {
var quit chan bool
for i := 0; i < 10; i++ {
go func(i int) {
for range time.Tick(time.Second * 2) {
select {
case <-quit:
return
default:
fmt.Println(i)
}
}
fmt.Println(i)
}(i)
}
select {}
}
想必大家,都想过了,用常用的 给 quit<-5,或者用 close(quit),来关闭,但第一个方法,不能保证关的是 i=5 的goroutine,第二种方法,针对结束 goroutine 里 range <-quit 使用。
2、解决方法
使用context包,保存每个goroutine 的context 和 cancel 函数,即可关闭 指定 goroutine。
package main
import (
"context"
"fmt"
"strconv"
"time"
)
func main() {
var goroutineContext map[int]context.Context
var goroutineContextCancel map[int]context.CancelFunc
goroutineContext = make(map[int]context.Context)
goroutineContextCancel = make(map[int]context.CancelFunc)
for i := 0; i < 10; i++ {
ctx, cancel := context.WithCancel(context.Background())
goroutineContext[i] = ctx
goroutineContextCancel[i] = cancel
go func(i int) {
for range time.Tick(time.Second * 1) {
select {
case <-goroutineContext[i].Done():
fmt.Println("goroutine exit ---- " + strconv.Itoa(i))
return
default:
fmt.Println(i)
}
}
fmt.Println(i)
}(i)
}
goroutineContextCancel[5]()
select {}
}
大家可以自行尝试The Go Playground