[toc]
前言
我们有很多情况下需要主动关闭goroutine,如需要实现一个系统自动熔断的功能就需要主动关闭goroutine
为什么要中断GoRoutine?
场景:
俩个相互依赖的的操作,“依赖”是指如果其中一个失败,那么另一个就没有意义,而不是第二个操作依赖第一个操作的结果(那种情况下,两个操作不能并行)。在这种情况下,如果我们很早就知道其中一个操作失败,那么我们就会希望能取消所有相关的操作。
goroutine介绍
goroutine是Go语言实现并发编程的利器,是 Go语言中的轻量级线程实现,由 Go 运行时(runtime)管理,简单的一个指令go function就能启动一个goroutine;Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU。
但是,Go语言并没有提供终止goroutine的接口,也就是说,我们不能从外部去停止一个goroutine,只能由goroutine内部退出(main函数终止除外);
几种停止的办法
1. 使用 for-range
for-range 从 channel 上接收值,直到 channel 关闭,该结构在Go并发编程中很常用,这对于从单一通道上获取数据去执行某些任务是十分方便的
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup //等待组,用来阻塞程序
func worker(ch chan int) {
defer wg.Done() //等待组 -1
for v := range ch {
fmt.Println(v)
}
}
func main() {
ch := make(chan int)
wg.Add(1) //等待组 +1
go worker(ch)
for i := 0; i
去掉close的情况
2. 使用 for-select (向退出通道发出退出信号)
当channel比较多时,for-range结构借不是很方便了;
Go语言提供了另外一种和channel相关的语法: select;
select能够让goroutine在多个通信操作上等待(可以理解为监听多个channel);
由于这个特性,for-select结构在Go并发编程中使用的频率很高;
我在使用Go的开发中,这是我用的最多的一种组合形式:
这里用 quit通道接收退出信号。
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func worker(in, quit
3. 使用for-select(关闭退出通道)
当我们就需要向 quit 通道中发送100次数据,如果再用以上的代码就很麻烦,有一个很简单的方法,关闭 channel,这样所有监听 quit channel 的 goroutine 就都会收到关闭信号。
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func worker(in, quit
4. 使用for-select(关闭多个channel)
如果select上监听了多个通道,需要所有的通道都关闭后才能结束goroutine,这里就利用select的一个特性,select不会在nil的通道上进行等待,因此将channel赋值为nil即可,此外,还需要利用channel的ok值。
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func worker(in1, in2
5. 使用context包
context包是官方提供的一个用于控制多个goroutine写作的包;
使用context的cancel信号,可以终止goroutine的运行,context是可以向下传递的
package main
import (
"context"
"errors"
"fmt"
"time"
)
func operation1(ctx context.Context) error {
// 让我们假设这个操作会因为某种原因失败
// 我们使用time.Sleep来模拟一个资源密集型操作
time.Sleep(100 * time.Millisecond)
return errors.New("failed")
}
func operation2(ctx context.Context) {
// 我们使用在前面HTTP服务器例子里使用过的类似模式
select {
case
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
我们正在努力让我们每次发布的库更加负责! 我们很荣幸宣布我们发布了 道德守则,并将作为一部分其放入 Diffusers 库的说明文档。 由于扩散模型在现实世界上的实际应用例子会对社会造成潜在的负面影响,该守则旨在引导对于社区做出贡献的 Diffusers 库…