Golang中为什么Context的Cancel会扩散而普通Channel不会

Golang中为什么Context的Cancel会扩散而普通Channel不会 为什么在下面的代码中,两个 goroutine 都能接收到 context 的取消信号,但无法同时接收到“普通通道”的信号? 通道是“点对点”的,因此随机只有一个 goroutine 会从 ch 通道接收数据。 但为什么两个 goroutine 总是能接收到 ctx.Done() 信号?

package main

import "sync"
import "fmt"
import "time"
import "context"

func main() {
	var wg sync.WaitGroup

	ch := make(chan struct{})
	wg.Add(2)
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		defer wg.Done()
		fmt.Println("start goroutine 1")
		for {
			select {
			case <- ch:
				fmt.Println("got ch at goroutine 1")
			case <- ctx.Done():
				fmt.Println("got done goroutine 1")
				return
			}
		}
	}()
	go func() {
		defer wg.Done()
		fmt.Println("start goroutine 2")
		for {
			select {
			case <- ch:
				fmt.Println("got ch at goroutine 2")
			case <- ctx.Done():
				fmt.Println("got done goroutine 2")
				return
			}
		}
	}()

	time.Sleep(time.Second)
	ch <- struct{}{}
	time.Sleep(time.Second)	
	cancel()
	fmt.Println("wait goroutines")
	wg.Wait()
}

输出:

apmattil@penguin:~/src/chan$ go run chan.go
start goroutine 1
start goroutine 2
got ch at goroutine 1
wait goroutines
got done goroutine 1
got done goroutine 2
apmattil@penguin:~/src/chan$ go run chan.go
start goroutine 2
start goroutine 1
got ch at goroutine 2
wait goroutines
got done goroutine 1
got done goroutine 2

更多关于Golang中为什么Context的Cancel会扩散而普通Channel不会的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中为什么Context的Cancel会扩散而普通Channel不会的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我来回答我自己的问题。

ctx.Done() 接收操作之所以有效,是因为上下文通道被关闭了。

如果你编辑以下代码,就能看到这一点:

	case _, ok := <-ctx.Done():
				fmt.Printf("got done goroutine 1 %t\n", ok)
				return
回到顶部