マスター Go の同時実行性: コンテキストの伝播とキャンセルの秘密が明らかに
Go の同時実行モデルは革新的ですが、複雑な同時操作の管理は難しい場合があります。ここで、コンテキストの伝播とキャンセルが登場します。これらの強力なツールを使用すると、複数のゴルーチン、さらにはネットワーク境界にまたがる、堅牢でキャンセル可能な操作を構築できます。
基本から始めましょう。コンテキスト パッケージは、期限、キャンセル シグナル、リクエスト スコープの値を API 境界を越えて、またプロセス間で伝達する方法を提供します。これは、長時間実行される操作を制御し、サービスを正常にシャットダウンするための秘密のソースです。
キャンセルにコンテキストを使用する簡単な例を次に示します。
func longRunningOperation(ctx context.Context) error { for { select { case <-ctx.Done(): return ctx.Err() default: // Do some work } } } func main() { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := longRunningOperation(ctx); err != nil { log.Printf("Operation cancelled: %v", err) } }
この例では、5 秒のタイムアウトを持つコンテキストを作成します。操作が時間内に完了しない場合、操作は自動的にキャンセルされます。
しかし、コンテキストはタイムアウトのためだけのものではありません。これを使用して、複数のゴルーチンにわたってキャンセル信号を伝播できます。これは、複雑なワークフローを管理するのに非常に役立ちます。
分散トランザクション システムを構築するシナリオを考えてみましょう。単一のトランザクションに複数のマイクロサービスが関与している可能性があり、いずれかの部分で障害が発生した場合にトランザクション全体がロールバックされるようにする必要があります。
コンテキストを使用してこれを構造化する方法は次のとおりです。
func performTransaction(ctx context.Context) error { // Start the transaction tx, err := db.BeginTx(ctx, nil) if err != nil { return err } defer tx.Rollback() // Will be no-op if tx.Commit() is called // Perform multiple operations if err := operation1(ctx); err != nil { return err } if err := operation2(ctx); err != nil { return err } if err := operation3(ctx); err != nil { return err } // If we've made it this far, commit the transaction return tx.Commit() } func operation1(ctx context.Context) error { // Make an HTTP request to another service req, err := http.NewRequestWithContext(ctx, "GET", "http://service1.example.com", nil) if err != nil { return err } resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() // Process the response... return nil }
この例では、コンテキストを使用して、データベース操作と HTTP リクエストの両方にキャンセルを伝達しています。コンテキストがいずれかの時点でキャンセルされると (タイムアウトまたは明示的なキャンセルにより)、すべての操作が終了し、リソースがクリーンアップされます。
しかし、キャンセルをさらに細かく制御する必要がある場合はどうすればよいでしょうか?そこでカスタム コンテキスト タイプが登場します。ドメイン固有のキャンセル シグナルを伝える独自のコンテキスト タイプを作成できます。
「優先度」値を含むカスタム コンテキストの例を次に示します。
type priorityKey struct{} func WithPriority(ctx context.Context, priority int) context.Context { return context.WithValue(ctx, priorityKey{}, priority) } func GetPriority(ctx context.Context) (int, bool) { priority, ok := ctx.Value(priorityKey{}).(int) return priority, ok } func priorityAwareOperation(ctx context.Context) error { priority, ok := GetPriority(ctx) if !ok { priority = 0 // Default priority } // Use the priority to make decisions... switch priority { case 1: // High priority operation case 2: // Medium priority operation default: // Low priority operation } return nil }
このカスタム コンテキストを使用すると、キャンセル信号とともに優先度情報を伝播できるため、同時操作をさらに細かく制御できるようになります。
ここで、正常なシャットダウンについて話しましょう。長時間実行されるサービスを構築する場合、シャットダウン信号を適切に処理して、操作がハングしたり、リソースがクリーンアップされないままにされたりしないようにすることが重要です。
コンテキストを使用して正常なシャットダウンを実装する方法は次のとおりです。
func main() { // Create a context that's cancelled when we receive an interrupt signal ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() // Start our main service loop errChan := make(chan error, 1) go func() { errChan <- runService(ctx) }() // Wait for either the service to exit or a cancellation signal select { case err := <-errChan: if err != nil { log.Printf("Service exited with error: %v", err) } case <-ctx.Done(): log.Println("Received shutdown signal. Gracefully shutting down...") // Perform any necessary cleanup // Wait for ongoing operations to complete (with a timeout) cleanupCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := performCleanup(cleanupCtx); err != nil { log.Printf("Cleanup error: %v", err) } } } func runService(ctx context.Context) error { // Run your service here, respecting the context for cancellation for { select { case <-ctx.Done(): return ctx.Err() default: // Do some work } } } func performCleanup(ctx context.Context) error { // Perform any necessary cleanup operations // This could include closing database connections, flushing buffers, etc. return nil }
この設定により、サービスが割り込み信号を受信したときに正常にシャットダウンできるようになり、リソースをクリーンアップして進行中の操作を終了する時間が与えられます。
Go のコンテキスト システムの最も強力な側面の 1 つは、ネットワーク境界を越えてキャンセルを伝播する機能です。これは、操作が複数のサービスにまたがる可能性がある分散システムを構築する場合に特に役立ちます。
これをマイクロサービス アーキテクチャで実装する方法の例を見てみましょう:
func longRunningOperation(ctx context.Context) error { for { select { case <-ctx.Done(): return ctx.Err() default: // Do some work } } } func main() { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := longRunningOperation(ctx); err != nil { log.Printf("Operation cancelled: %v", err) } }
この例では、クエリ パラメーターに基づいてタイムアウトを設定したコンテキストを作成しています。このコンテキストは、後続のすべての API 呼び出しを通じて伝播されます。タイムアウトに達すると、進行中のすべての操作がキャンセルされ、クライアントにエラーが返されます。
このパターンにより、クライアントが応答の待機を放棄した後も長時間継続する「暴走」操作が発生しないことが保証されます。これは、応答性が高く、リソース効率の高い分散システムを構築するための重要な部分です。
同時実行システムでのエラー処理は難しい場合がありますが、ここでもコンテキストが役に立ちます。コンテキストを使用することで、エラーが正しく伝播され、エラーが発生した場合でもリソースがクリーンアップされることを保証できます。
これは、同時操作でエラーを処理する方法の例です:
func performTransaction(ctx context.Context) error { // Start the transaction tx, err := db.BeginTx(ctx, nil) if err != nil { return err } defer tx.Rollback() // Will be no-op if tx.Commit() is called // Perform multiple operations if err := operation1(ctx); err != nil { return err } if err := operation2(ctx); err != nil { return err } if err := operation3(ctx); err != nil { return err } // If we've made it this far, commit the transaction return tx.Commit() } func operation1(ctx context.Context) error { // Make an HTTP request to another service req, err := http.NewRequestWithContext(ctx, "GET", "http://service1.example.com", nil) if err != nil { return err } resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() // Process the response... return nil }
この例では、チャネルを使用して、ゴルーチンからメイン関数にエラーを伝えています。キャンセルのコンテキストも確認しています。これにより、操作自体からのエラーとコンテキストからのキャンセルの両方を確実に処理できます。
コンテキストの見落とされがちな側面の 1 つは、リクエスト スコープの値を運ぶ能力です。これは、リクエスト ID、認証トークン、その他のメタデータなどを API 境界を越えて伝播する場合に非常に役立ちます。
これを使用する例を次に示します:
type priorityKey struct{} func WithPriority(ctx context.Context, priority int) context.Context { return context.WithValue(ctx, priorityKey{}, priority) } func GetPriority(ctx context.Context) (int, bool) { priority, ok := ctx.Value(priorityKey{}).(int) return priority, ok } func priorityAwareOperation(ctx context.Context) error { priority, ok := GetPriority(ctx) if !ok { priority = 0 // Default priority } // Use the priority to make decisions... switch priority { case 1: // High priority operation case 2: // Medium priority operation default: // Low priority operation } return nil }
この例では、ミドルウェアを使用してリクエスト ID をコンテキストに追加しています。このリクエスト ID は取得され、このコンテキストを受け取る後続のハンドラーまたは関数で使用できます。
最後に、コンテキストは強力なツールではありますが、特効薬ではないことに注意してください。コンテキストを過度に使用すると、理解や保守が困難なコードが作成される可能性があります。コンテキストを慎重に使用し、API を慎重に設計することが重要です。
コンテキストの主な用途は、期限、キャンセル信号、リクエストスコープの値を API 境界を越えて伝達することであることに注意してください。これは、オプションのパラメーターを関数に渡すための汎用メカニズムを意図したものではありません。
結論として、コンテキストの伝播とキャンセルを含む Go の同時実行モデルをマスターすることが、堅牢で効率的でスケーラブルなアプリケーションを構築する鍵となります。これらのツールを活用することで、複雑なワークフローを適切に処理し、リソースを効果的に管理し、変化する状況にインテリジェントに対応するシステムを構築できます。私たちが並行プログラミングで可能なことの限界を押し広げ続けるにつれて、これらのテクニックは私たちのツールボックスにおいてさらに重要なものになるでしょう。
私たちの作品
私たちの作品をぜひチェックしてください:
インベスターセントラル | スマートな暮らし | エポックとエコー | 不可解な謎 | ヒンドゥーヴァ | エリート開発者 | JS スクール
私たちは中程度です
Tech Koala Insights | エポックズ&エコーズワールド | インベスター・セントラル・メディア | 不可解な謎 中 | 科学とエポックミディアム | 現代ヒンドゥーヴァ
以上がマスター Go の同時実行性: コンテキストの伝播とキャンセルの秘密が明らかにの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











OpenSSLは、安全な通信で広く使用されているオープンソースライブラリとして、暗号化アルゴリズム、キー、証明書管理機能を提供します。ただし、その歴史的バージョンにはいくつかの既知のセキュリティの脆弱性があり、その一部は非常に有害です。この記事では、Debian SystemsのOpenSSLの共通の脆弱性と対応測定に焦点を当てます。 Debianopensslの既知の脆弱性:OpenSSLは、次のようないくつかの深刻な脆弱性を経験しています。攻撃者は、この脆弱性を、暗号化キーなどを含む、サーバー上の不正な読み取りの敏感な情報に使用できます。

Beegoormフレームワークでは、モデルに関連付けられているデータベースを指定する方法は?多くのBEEGOプロジェクトでは、複数のデータベースを同時に操作する必要があります。 Beegoを使用する場合...

バックエンド学習パス:フロントエンドからバックエンドへの探査の旅は、フロントエンド開発から変わるバックエンド初心者として、すでにNodeJSの基盤を持っています...

Golandのカスタム構造ラベルが表示されない場合はどうすればよいですか?ゴーランドを使用するためにGolandを使用する場合、多くの開発者はカスタム構造タグに遭遇します...

Go Crawler Collyのキュースレッドの問題は、Go言語でColly Crawler Libraryを使用する問題を調査します。 �...

redisstreamを使用してGo言語でメッセージキューを実装する問題は、GO言語とRedisを使用することです...

この記事では、自動拡張を実現するためにDebianシステムでMongodbを構成する方法を紹介します。主な手順には、Mongodbレプリカセットとディスクスペース監視のセットアップが含まれます。 1。MongoDBのインストール最初に、MongoDBがDebianシステムにインストールされていることを確認してください。次のコマンドを使用してインストールします。sudoaptupdatesudoaptinstinstall-yymongodb-org2。mongodbレプリカセットMongodbレプリカセットの構成により、自動容量拡張を達成するための基礎となる高可用性とデータ冗長性が保証されます。 Mongodbサービスを開始:Sudosystemctlstartmongodsudosys
