Go Context:キャンセルと伝播

import "context"

コンテキストパッケージのソースコードを表示します!
コンテキストを使用するサーバーのサンプルコードを参照してください。
コンテキストに関するgolangドキュメントを表示してください!

サンドイッチを作る必要があるとすると、トマト、パン、ハムを購入するために3人を手配します。ハムの買い手は、スーパーに着いたときにハムがないことに気づいたので、スーパーの店員にその場でハムを作ってもらいました。パンとトマトを買う人は、それぞれパン屋とトマトショップに行く途中です。
この時、いきなりハムを食べないことにしたのですが、資源を無駄にしないためには、ハムメーカーがハムを作るのをやめ、スーパーに行く人がすぐにスーパーに行くのをやめ、人がハムを待つことはすぐにハムを待つことをやめます。

カスタム機能sleepAndTalk()-

func sleepAndTalk(ctx context.Context, d time.Duration, msg string) {
    
    
	select {
    
    
	case <- time.After(d)
		fmt.Println(msg)
	case <- ctx.Done()
		log.Print(ctx.Err())
	}
}

キャンセル-

func main() {
    
    
	ctx := Context.Background()
	ctx, cancel := context.WithCancel(ctx)
	go func () {
    
    
		s := bufio.NewScanner(os.Stdin)
		s.Scan()
		cancel()
	}()
	sleepAndTalk(ctx, 5 * time.Second, "Hello")
}

go run *.go上記のコードを実行することにより、そうでない場合はStdin、5秒後に出力しますHello5秒以内であればStdin、すぐcancelに実行さsleepAndTalk()ます。

func main() {
    
    
	ctx := Context.Background()
	ctx, cancel := context.WithCancel(ctx)
	go func () {
    
    
		time.Sleep(time.Second)
		cancel()
	}()
	sleepAndTalk(ctx, 5 * time.Second, "Hello")
}

Cancel()1秒後。上記のコードは-と同等です

func main() {
    
    
	ctx := Context.Background()
	ctx, cancel := context.WithCancel(ctx)
	time.AfterFunc(time.Second, cancel)
	sleepAndTalk(ctx, 5 * time.Second, "Hello")
}

または-

func main() {
    
    
	ctx := Context.Background()
	ctx, cancel := context.WithTimeout(ctx, time.Second)
	cancel() // release resources for timer
	sleepAndTalk(ctx, 5 * time.Second, "Hello")
}

キャンセルを処理するメソッド-

Background()
WithCancel()
WithTimeout()
WithDeadline()

チャネルとオプションを使用する

func main() {
    
    
	stop := make(chan bool)
	go func() {
    
    
		for {
    
    
			select {
    
    
			case <- stop: // 在channel收到值后输出stop并返回
				fmt.Println("stop!")	
				return
			default: // 在channel收到任何bool之前一直会跑default
				fmt.Println("running...")
				time.Sleep(1 * time.Second)
			}
		}
	}()
	
	time.Sleep(5 * time.Second)
	fmt.Println("sending value to channel \"stop\"")
	stop <- true
	time.Sleep(5 * time.Second)
} 

チャネルと選択は、複雑なスレッドツリーを処理できません。
コンテキストは大丈夫ですか?

func main() {
    
    
	// Background() is the root Context
	// WithCancel() add a new Context node
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
    
    
		for {
    
    
			select {
    
    
			case <- ctx.Done(): // Done()在引用cancel()之后打开channel
				fmt.Println("stop!")	
				return
			default: // 在channel收到任何bool之前一直会跑default
				fmt.Println("running...")
				time.Sleep(1 * time.Second)
			}
		}
	}()

	time.Sleep(5 * time.Second)
	fmt.Println("sending value to channel \"stop\"")
	cancel()
	time.Sleep(5 * time.Second)

}

複数のスレッドの例-

func main() {
    
    
	ctx, cancel := context.WithCancel(context.Background())
	go worker(ctx, node1)
	go worker(ctx, node2)
	go worker(ctx, node3)
	time.Sleep(5 * time.Second)
	fmt.Println("sending value to channel \"stop\"")
	cancel()
	time.Sleep(5 * time.Second)
}

func worker(ctx context.Context, name string) {
    
    
	go func() {
    
    
		for {
    
    
			select {
    
    
			case <- ctx.Done(): // Done()在引用cancel()之后打开channel
				fmt.Println(name, "stop!")	
				return
			default: // 在channel收到任何bool之前一直会跑default
				fmt.Println(name, "running...")
				time.Sleep(1 * time.Second)
			}
		}
	}
}

おすすめ

転載: blog.csdn.net/Hita999/article/details/112768767