日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

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

Golang 中的 Context 包

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

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

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

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

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

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

它是如何工作的

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

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

(2) 設置超時:接下來,我們可以在上下文中設置超時。這就好比你決定在排隊多久后放棄并去嘗試其他游樂設施。Xdh28資訊網——每日最新資訊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) 檢查超時:現在,我們可以使用上下文來檢查是否等待時間太長,是否應該停止我們的任務。這就好比在排隊等待時看看手表。Xdh28資訊網——每日最新資訊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) 取消上下文:最后,如果出于某種原因需要停止任務,我們可以取消上下文。這就好比聽到因下雨而宣布過山車關閉。Xdh28資訊網——每日最新資訊28at.com

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

示例 1:慢速數據庫查詢

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

示例 2:網頁抓取

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

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

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

示例4:HTTP 服務器

假設你正在構建一個處理傳入請求的 HTTP 服務器。一些請求可能需要很長時間來處理,你希望設置一個最長處理時間限制。Xdh28資訊網——每日最新資訊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秒的時間,上下文將被取消,并且服務器將響應“操作超時”。Xdh28資訊網——每日最新資訊28at.com

示例5:同步多個 Goroutines

假設你正在編寫一個程序,使用 Goroutines 并發執行多個任務。如果其中一個任務失敗,你希望取消所有其他任務。Xdh28資訊網——每日最新資訊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(),從而允許它們進行清理并退出。Xdh28資訊網——每日最新資訊28at.com

仍然在嘗試理解嗎?

當我第一次接觸上下文時,我感到非常困惑,我提出了一個問題,即如果 select 前面的命令花費太長時間,那么我們永遠無法檢測到 取消,這是一個合理的問題。因此,我準備了另一個示例來詳細解釋這種情況。Xdh28資訊網——每日最新資訊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 語句不會被執行,直到休眠時間已經過去。Xdh28資訊網——每日最新資訊28at.com

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

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

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

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

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

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

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

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

標簽:
  • 熱門焦點
  • 盧偉冰長文解析K60至尊版 對Redmi有著里程碑式的意義

    在今天的Redmi后性能時代戰略發布會結束之后,Redmi總經理盧偉冰又帶來了一篇長文,詳解了為什么 Redmi 要開啟后性能時代?為什么選擇和 MediaTek、Pixelworks 深度合作?以及后性
  • 官方承諾:K60至尊版將會首批升級MIUI 15

    全新的MIUI 15今天也有了消息,在官宣了K60至尊版將會搭載天璣9200+處理器和獨顯芯片X7的同時,Redmi給出了官方承諾,K60至尊重大更新首批升級,會首批推送MIUI 15。也就是說雖然
  • K8S | Service服務發現

    一、背景在微服務架構中,這里以開發環境「Dev」為基礎來描述,在K8S集群中通常會開放:路由網關、注冊中心、配置中心等相關服務,可以被集群外部訪問;圖片對于測試「Tes」環境或者
  • 雅柏威士忌多款單品價格大跌,泥煤頂流也不香了?

    來源 | 烈酒商業觀察編 | 肖海林今年以來,威士忌市場開始出現了降溫跡象,越來越多不斷暴漲的網紅威士忌也開始悄然回歸市場理性。近日,LVMH集團旗下蘇格蘭威士忌品牌雅柏(Ardbeg
  • 2023年,我眼中的字節跳動

    此時此刻(2023年7月),字節跳動從未上市,也從未公布過任何官方的上市計劃;但是這并不妨礙它成為中國最受關注的互聯網公司之一。從2016-17年的抖音強勢崛起,到2018年的&ldquo;頭騰
  • 網紅炒股不為了賺錢,那就是耍流氓!

    來源:首席商業評論6月26日高調宣布入市,網絡名嘴大v胡錫進居然進軍了股市。在一次財經媒體峰會上,幾個財經圈媒體大佬就&ldquo;胡錫進炒股是否知道認真報道&rdquo;展開討論。有
  • 馮提莫簽約抖音公會 前“斗魚一姐”消失在直播間

    來源:直播觀察提起&ldquo;馮提莫&rdquo;這個名字,很多網友或許聽過,但應該不記得她是哪位主播了。其實,作為曾經的&ldquo;斗魚一姐&rdquo;,馮提莫在游戲直播的年代影響力不輸于現
  • 認真聊聊東方甄選:如何告別低垂的果實

    來源:山核桃作者:財經無忌爆火一年后,俞敏洪和他的東方甄選依舊是頗受外界關心的&ldquo;網紅&rdquo;。7月5日至9日,為期5天的東方甄選&ldquo;甘肅行&rdquo;首次在自有App內直播,
  • 華為和江淮汽車合作開發百萬元問界MPV?雙方回應來了

    8月1日消息,郭明錤今天在社交平臺發文稱,華為正在和江淮汽車合作,開發售價在100萬元的問界MPV,預計在2024年第2季度量產,銷量目標為上市首年交付5萬輛。
Top 主站蜘蛛池模板: 清河县| 同仁县| 荥阳市| 罗平县| 阿克苏市| 胶州市| 葫芦岛市| 阳朔县| 特克斯县| 申扎县| 台湾省| 论坛| 水城县| 梧州市| 大竹县| 广元市| 鄂伦春自治旗| 东港市| 固始县| 梧州市| 凭祥市| 聂拉木县| 临海市| 东台市| 沂南县| 双牌县| 贺兰县| 甘谷县| 越西县| 无锡市| 本溪市| 华池县| 大姚县| 湟中县| 德兴市| 托克托县| 武强县| 岑溪市| 江华| 义马市| 交口县|