取消進行中的操作
您可以使用 Go context.Context
管理進行中的操作。Context
是一個標準的 Go 資料值,它可以報告它所代表的整個操作是否已被取消且不再需要。透過在應用程式的函式呼叫和服務之間傳遞 context.Context
,這些函式和服務可以在其處理不再需要時提前停止工作並返回錯誤。有關 Context
的更多資訊,請參閱Go 併發模式:Context。
例如,您可能希望
- 結束長時間執行的操作,包括耗時過長的資料庫操作。
- 從其他地方傳播取消請求,例如當客戶端關閉連線時。
許多針對 Go 開發人員的 API 都包含接受 Context
引數的方法,這使得您可以在整個應用程式中更輕鬆地使用 Context
。
在超時後取消資料庫操作
您可以使用 Context
設定超時或截止時間,在該時間之後操作將被取消。要派生具有超時或截止時間的 Context
,請呼叫 context.WithTimeout
或 context.WithDeadline
。
以下超時示例中的程式碼派生了一個 Context
並將其傳遞給 sql.DB
的 QueryContext
方法。
func QueryWithTimeout(ctx context.Context) {
// Create a Context with a timeout.
queryCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
// Pass the timeout Context with a query.
rows, err := db.QueryContext(queryCtx, "SELECT * FROM album")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// Handle returned rows.
}
當一個上下文從外部上下文派生時,例如本例中 queryCtx
從 ctx
派生,如果外部上下文被取消,那麼派生上下文也會自動取消。例如,在 HTTP 伺服器中,http.Request.Context
方法返回與請求關聯的上下文。如果 HTTP 客戶端斷開連線或取消 HTTP 請求(在 HTTP/2 中可能),該上下文將被取消。將 HTTP 請求的上下文傳遞給上面的 QueryWithTimeout
將導致資料庫查詢提前停止,**如果**整個 HTTP 請求被取消,**或者**如果查詢花費了超過五秒鐘。
注意:在建立具有超時或截止時間的新 Context
時,請務必延遲呼叫返回的 cancel
函式。這會在包含函式退出時釋放新 Context
持有的資源。它還會取消 queryCtx
,但當函式返回時,應該沒有任何東西再使用 queryCtx
了。