AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

Golang 中的 Context 包

來源: 責編: 時間:2023-11-14 09:10:08 311觀看
導讀今天,我們將討論 Go 編程中非常重要的一個主題:context 包。如果你現在覺得它很令人困惑,不用擔心 — 在本文結束時,你將像專家一樣處理 context!想象一下,你在一個主題公園,興奮地準備搭乘一座巨大的過山車。但有個問題:排隊

今天,我們將討論 Go 編程中非常重要的一個主題:context 包。如果你現在覺得它很令人困惑,不用擔心 — 在本文結束時,你將像專家一樣處理 context!HNA28資訊網——每日最新資訊28at.com

想象一下,你在一個主題公園,興奮地準備搭乘一座巨大的過山車。但有個問題:排隊的人非常多,而且公園快要關門,你只有一個小時的時間。你會怎么辦?嗯,你可能會等一會兒,但不會等一個小時,對吧?如果你等了 30 分鐘還沒有到前面,你會離開隊伍去嘗試其他游樂設施。這就是我們所謂的 '超時'。HNA28資訊網——每日最新資訊28at.com

HNA28資訊網——每日最新資訊28at.com

現在,想象一下,你還在排隊,突然下起了傾盆大雨。過山車的操作員決定關閉過山車。你不會繼續排隊等待根本不會發生的事情,對吧?你會立刻離開隊伍。這就是我們所謂的 '取消'。HNA28資訊網——每日最新資訊28at.com

在編程世界中,我們經常面臨類似的情況。我們要求程序執行可能需要很長時間或需要因某種原因停止的任務。這就是 context 包發揮作用的地方。它允許我們優雅地處理這些超時和取消。HNA28資訊網——每日最新資訊28at.com

它是如何工作的

(1) 創建上下文:我們首先創建一個上下文。這就像排隊等待過山車一樣。HNA28資訊網——每日最新資訊28at.com

ctx := context.Background() // This gives you an empty context

(2) 設置超時:接下來,我們可以在上下文中設置超時。這就好比你決定在排隊多久后放棄并去嘗試其他游樂設施。HNA28資訊網——每日最新資訊28at.com

ctxWithTimeout, cancel := context.WithTimeout(ctx, time.Second*10) // Wait for 10 seconds// Don't forget to call cancel when you're done, or else you might leak resources!defer cancel()

(3) 檢查超時:現在,我們可以使用上下文來檢查是否等待時間太長,是否應該停止我們的任務。這就好比在排隊等待時看看手表。HNA28資訊網——每日最新資訊28at.com

select {case <-time.After(time.Second * 15): // This task takes 15 seconds    fmt.Println("Finished the task")case <-ctxWithTimeout.Done():    fmt.Println("We've waited too long, let's move on!") // We only wait for 10 seconds}

(4) 取消上下文:最后,如果出于某種原因需要停止任務,我們可以取消上下文。這就好比聽到因下雨而宣布過山車關閉。HNA28資訊網——每日最新資訊28at.com

cancel() // We call the cancel function we got when we created our context with timeout

示例 1:慢速數據庫查詢

想象一下構建一個從數據庫中獲取用戶數據的Web應用程序。有時,數據庫響應較慢,你不希望用戶永遠等下去。在這種情況下,你可以使用帶有超時的上下文。HNA28資訊網——每日最新資訊28at.com

func getUser(ctx context.Context, id int) (*User, error) {    // Create a new context that will be cancelled if it takes more than 3 seconds    ctx, cancel := context.WithTimeout(ctx, 3*time.Second)    defer cancel()    // Assume db.QueryRowContext is a function that executes a SQL query and returns a row    row := db.QueryRowContext(ctx, "SELECT name FROM users WHERE id = ?", id)    var name string    if err := row.Scan(&name); err != nil {        return nil, err    }    return &User{Name: name}, nil}

在這個示例中,如果數據庫查詢花費超過3秒的時間,上下文將被取消,db.QueryRowContext 應返回一個錯誤。HNA28資訊網——每日最新資訊28at.com

示例 2:網頁抓取

假設你正在編寫一個用于從網站抓取數據的程序。然而,該網站有時響應較慢,或者根本不響應。你可以使用上下文來防止你的程序陷入困境。HNA28資訊網——每日最新資訊28at.com

func scrapeWebsite(ctx context.Context, url string) (*html.Node, error) {    // Create a new context that will be cancelled if it takes more than 5 seconds    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)    defer cancel()    // Create a request with the context    req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)    if err != nil {        return nil, err    }    // Execute the request    resp, err := http.DefaultClient.Do(req)    if err != nil {        return nil, err    }    defer resp.Body.Close()    // Parse the response body as HTML    return html.Parse(resp.Body), nill}

在這個示例中,如果從網站獲取數據超過5秒,上下文將被取消,http.DefaultClient.Do 應該返回一個錯誤。HNA28資訊網——每日最新資訊28at.com

示例3:長時間運行的任務

假設你有一個執行長時間運行任務的程序,但你希望能夠在程序接收到關閉信號時停止任務。這在一個 Web 服務器中可能會很有用,當關閉時必須停止提供請求并進行清理。HNA28資訊網——每日最新資訊28at.com

func doTask(ctx context.Context) {    for {        select {        case <-time.After(1 * time.Second):            // The task is done, we're ready to exit            fmt.Println("Task is done")            return        case <-ctx.Done():            // The context was cancelled from the outside, clean up and exit            fmt.Println("Got cancel signal, cleaning up")            return        }    }}func main() {    // Create a new context    ctx, cancel := context.WithCancel(context.Background())    // Start the task in a goroutine    go doTask(ctx)    // Wait for a shutdown signal    <-getShutdownSignal()    // Cancel the context, which will stop the task    cancel()    // Wait for a bit to allow the task to clean up    time.Sleep(1 * time.Second)}

在這個示例中,當程序接收到關閉信號時,它會取消上下文,這會導致 doTask 在 <-ctx.Done() 上接收到信號。HNA28資訊網——每日最新資訊28at.com

示例4:HTTP 服務器

假設你正在構建一個處理傳入請求的 HTTP 服務器。一些請求可能需要很長時間來處理,你希望設置一個最長處理時間限制。HNA28資訊網——每日最新資訊28at.com

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {    ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)    defer cancel()    // Simulate a long-running operation    select {    case <-time.After(3 * time.Second):        w.Write([]byte("Operation finished."))    case <-ctx.Done():        w.Write([]byte("Operation timed out."))    }})http.ListenAndServe(":8080", nil)

在這個示例中,如果操作需要超過2秒的時間,上下文將被取消,并且服務器將響應“操作超時”。HNA28資訊網——每日最新資訊28at.com

示例5:同步多個 Goroutines

假設你正在編寫一個程序,使用 Goroutines 并發執行多個任務。如果其中一個任務失敗,你希望取消所有其他任務。HNA28資訊網——每日最新資訊28at.com

func doTask(ctx context.Context, id int) {    select {    case <-time.After(time.Duration(rand.Intn(4)) * time.Second):        fmt.Printf("Task %v finished./n", id)    case <-ctx.Done():        fmt.Printf("Task %v cancelled./n", id)    }}func main() {    ctx, cancel := context.WithCancel(context.Background())    for i := 1; i <= 5; i++ {        go doTask(ctx, i)    }    // Cancel the context after 2 seconds    time.Sleep(2 * time.Second)    cancel()    // Give the tasks some time to finish up    time.Sleep(1 * time.Second)}

在這個示例中,當上下文被取消時,仍在運行的任何任務都將收到 <-ctx.Done(),從而允許它們進行清理并退出。HNA28資訊網——每日最新資訊28at.com

仍然在嘗試理解嗎?

當我第一次接觸上下文時,我感到非常困惑,我提出了一個問題,即如果 select 前面的命令花費太長時間,那么我們永遠無法檢測到 取消,這是一個合理的問題。因此,我準備了另一個示例來詳細解釋這種情況。HNA28資訊網——每日最新資訊28at.com

package mainimport ( "context" "fmt" "math/rand" "time")func expensiveCalculation(ctx context.Context, resultChan chan<- int) { // Simulate a long-running calculation rand.Seed(time.Now().UnixNano()) sleepTime := time.Duration(rand.Intn(20)+1) * time.Second fmt.Printf("Calculation will take %s to complete/n", sleepTime) time.Sleep(sleepTime) select { case <-ctx.Done():  // Context was cancelled, don't write to the channel  return default:  // Write the result to the channel  resultChan <- 42 // replace with your actual calculation result }}func main() { // Create a context that will be cancelled after 10 seconds ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() // The cancel should be deferred so resources are cleaned up resultChan := make(chan int) // Start the expensive calculation in a separate goroutine go expensiveCalculation(ctx, resultChan) // Wait for either the result or the context to be done select { case res := <-resultChan:  // Got the result  fmt.Printf("Calculation completed with result: %d/n", res) case <-ctx.Done():  // Context was cancelled  fmt.Println("Calculation cancelled") }}

time.Sleep(sleepTime) 命令是阻塞的,將暫停 goroutine 的執行,直到指定的持續時間已過。這意味著 select 語句不會被執行,直到休眠時間已經過去。HNA28資訊網——每日最新資訊28at.com

然而,上下文的取消與 goroutine 內的執行是獨立的。如果上下文的截止時間被超過或其 cancel() 函數被調用,它的 Done() 通道將被關閉。HNA28資訊網——每日最新資訊28at.com

在主 goroutine 中,您有另一個 select 語句,它將立即檢測上下文的 Done() 通道是否已關閉,并在不等待 expensiveCalculation goroutine 完成休眠的情況下打印 **"Calculation cancelled"**。HNA28資訊網——每日最新資訊28at.com

也就是說,expensiveCalculation goroutine 將在休眠后繼續執行,它將在嘗試寫入 resultChan 之前檢查上下文是否已被取消。如果已被取消,它將立即返回。這是為了避免潛在的死鎖,如果沒有其他goroutine從 resultChan 讀取。HNA28資訊網——每日最新資訊28at.com

如果需要昂貴的計算(在本例中由 time.Sleep 模擬)在取消時立即停止,您必須設計計算以周期性地檢查上下文是否已取消。這通常在需要將計算分解為較小部分的情況下使用循環。如果計算不能分解,并需要一次運行完畢,那么很遺憾,在 Go 中無法提前停止它。HNA28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-24320-0.htmlGolang 中的 Context 包

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: C 語言編譯器(IDE)初學者指南:選擇適合你的工具

下一篇: 使用Python進行文本分析-將PDF文件多進程批量處理為csv文件

標簽:
  • 熱門焦點
Top