about the key ”defer”and “select” in Go

huangapple go评论76阅读模式
英文:

about the key ”defer”and “select” in Go

问题

func TestContext(t *testing.T) {
	message := make(chan int, 10)
	//producer
	for i := 0; i < 10; i++ {
		message <- i
	}

	//consumer
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)

	go func(ctx context.Context) {
		ticker := time.NewTicker(1 * time.Second)
		for _ = range ticker.C {
			select {
			case <-ctx.Done():
				fmt.Println("子进程中断...")
				return
			default:
				fmt.Printf("发送消息:%d\n", <-message)
			}
		}
	}(ctx)

	defer close(message)
	defer cancel()
	select {
	case <-ctx.Done():
		//time.Sleep(1*time.Second)
		fmt.Println("主进程退出!")
	}
}

Q1: "defer cancel" 什么时候执行?在 select 之后吗?

Q2: 在 Q1 中,如果 "defer cancel" 在 select 之后执行,ctx.Done() 会返回 nil 吗?select 会被阻塞吗?

英文:
func TestContext(t *testing.T){
	message:=make(chan int,10)
	//producer
	for i:=0;i&lt;10;i++{
		message&lt;-i
	}
	
	//consumer
	ctx,cancel:=context.WithTimeout(context.Background(),time.Second*5)

	go func(ctx context.Context) {
			ticker := time.NewTicker(1 * time.Second)
			for _ = range ticker.C { 
				select {
				case &lt;-ctx.Done():
					fmt.Println(&quot;child process interrupt...&quot;)
					return
				default:
					fmt.Printf(&quot;send message: %d\n&quot;, &lt;-message)
				}
			}
		}(ctx)
	
	defer close(message)
	defer cancel()
	select{
		case &lt;-ctx.Done():
			//time.Sleep(1*time.Second)
			fmt.Println(&quot;main process exit!&quot;)
	}

}

Q1: when is the “defer cancel” executed? after select ?

Q2: In Q1,if "defer cancel" is executed after select , will the ctx.Done() return nil? and will the select be blocked?

答案1

得分: 3

所有延迟的函数调用将在函数体运行之后但在函数返回之前执行,所以是的,defer cancel会在select之后执行。

select会阻塞直到上下文超时。当上下文超时时,<-ctx.Done()的情况将被启用,所以select可以在上下文超时后继续执行。

英文:

All deferred function calls will run after the function body runs, but before the function returns, so yes, defer cancel will execute after select.

Select will block until the context times out. When the context times out, the &lt;-ctx.Done() case will be enabled, so select can continue after the context timeout.

huangapple
  • 本文由 发表于 2021年11月10日 13:50:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/69908478.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定