1.7 版本时候增加此功能。提供优雅处理goroutine的协同方式
如何通知一个goroutine 需要退出了?
全局变量
var notity = false
var wg sync.WaitGroup
func con() {
defer wg.Done()
for {
fmt.Println("执行任务")
time.Sleep(time.Millisecond * 300)
if notity {
break
}
}
}
func main() {
wg.Add(1)
go con()
time.Sleep(time.Second * 2)
notity = true
wg.Wait()
}
利用channel
var wg sync.WaitGroup
var notityChan = make(chan bool, 1)
func con() {
defer wg.Done()
LOOP:
for {
fmt.Println("执行任务")
time.Sleep(time.Millisecond * 500)
select {
case <-notityChan:
break LOOP
default:
}
}
}
func main() {
wg.Add(1)
go con()
time.Sleep(time.Second * 5)
notityChan <- true
wg.Wait()
}
使用context
func con(ctx context.Context) {
defer wg.Done()
LOOP:
for {
fmt.Println("执行任务")
time.Sleep(time.Millisecond * 500)
select {
case <-ctx.Done():
break LOOP
default:
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
wg.Add(1)
go con(ctx)
time.Sleep(time.Second * 5)
cancel()
wg.Wait()
}
使用context与channel的区别
实际上原理没什么区别!哈哈哈哈
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
if parent == nil {
panic("cannot create context from nil parent")
}
c := newCancelCtx(parent)
propagateCancel(parent, &c)
return &c, func() { c.cancel(true, Canceled) }
}
从WithCancel方法看。通过传递ctx 可以将gouroutine串起来。
func propagateCancel(parent Context, child canceler) {
done := parent.Done()
if done == nil {
return // parent is never canceled
}
select {
case <-done:
// parent is already canceled
child.cancel(false, parent.Err())
return
default:
}
if p, ok := parentCancelCtx(parent); ok {
p.mu.Lock()
if p.err != nil {
// parent has already been canceled
child.cancel(false, p.err)
} else {
if p.children == nil {
p.children = make(map[canceler]struct{})
}
p.children[child] = struct{}{}
}
p.mu.Unlock()
} else {
atomic.AddInt32(&goroutines, +1)
go func() {
select {
case <-parent.Done():
child.cancel(false, parent.Err())
case <-child.Done():
}
}()
}
}
其内部操作实际上还是借用了channel
Done() <-chan struct{} // Done 方法传递一个空的struct
无论是channel还是全局变量。又或者是channel 标志是布尔,是struct,是int .再处理goroutine这一件事上,不同人解决办法思路都不一样。而go 提供优雅的解决办法,希望能统一风格,一如代码格式化。