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

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

Go語言中的context包到底解決了啥問題?

來源: 責編: 時間:2024-06-05 17:34:21 217觀看
導讀Go語言,自2009年發布以來,憑借其簡潔、高效、并發能力強等特點,迅速在開發者社區獲得了廣泛的關注和應用,特別是在服務器端開發、云計算、容器技術和微服務架構等領域。例如,Docker 和 K8S 等知名的容器技術都是使用Go語言

Go語言,自2009年發布以來,憑借其簡潔、高效、并發能力強等特點,迅速在開發者社區獲得了廣泛的關注和應用,特別是在服務器端開發、云計算、容器技術和微服務架構等領域。例如,Docker 和 K8S 等知名的容器技術都是使用Go語言開發的。n3C28資訊網——每日最新資訊28at.com

為什么需要Context包?

認識 goroutine

首先讓我們來認識下 goroutine。n3C28資訊網——每日最新資訊28at.com

Go語言的高并發、高性能都來源于它的并發模型:goroutine,就是它,讓開發者可以輕松地編寫高吞吐量的應用程序,這在處理大量并發請求的服務器端開發中尤為重要。n3C28資訊網——每日最新資訊28at.com

goroutine是Go語言中的輕量級線程,或者稱為協程。與操作系統級別的線程相比,goroutine的創建和銷毀開銷非常小,調度效率也很高,因此在Go語言中,可以輕松地創建成千上萬個goroutine來處理并發任務。n3C28資訊網——每日最新資訊28at.com

使用goroutine非常簡單,只需在函數調用前加上go關鍵字即可。例如:n3C28資訊網——每日最新資訊28at.com

go func() {    // 并發執行的代碼}()

并發編程的挑戰

goroutine 雖然讓并發編程變得非常方便,但也帶來了新的挑戰。n3C28資訊網——每日最新資訊28at.com

  • 超時控制:許多操作(如網絡請求、數據庫查詢等)都可能因為各種原因變得緩慢甚至無限期掛起。如果沒有合適的超時控制機制,這些操作可能會導致計算機資源被長時間占用,影響系統的整體性能和響應速度。
  • 取消操作:某些情況下,某些操作可能需要被取消。例如,當用戶取消了一個正在進行的請求,或者當某個前置條件不再滿足時,我們需要能夠及時地取消正在進行的操作,以避免不必要的資源消耗。
  • 數據傳遞:不同的goroutine之間可能需要共享和傳遞一些上下文信息。例如,在一個請求的處理過程中,我們可能需要在多個函數調用之間傳遞用戶身份、請求ID等。這些信息需要能夠安全地在多個goroutine之間傳遞和共享。

這些挑戰在其它語言的并發編程模型中也是廣泛存在的。n3C28資訊網——每日最新資訊28at.com

為什么需要context包

為了解決并發編程中的常見挑戰,Go語言引入了context包。context包提供了一種統一的機制來管理請求的生命周期,傳遞取消信號,設置超時時間,并在不同的goroutine之間傳遞上下文信息。n3C28資訊網——每日最新資訊28at.com

  • 統一管理請求生命周期:context包允許我們為每一個請求創建一個上下文對象(上下文通常就翻譯為context),并在請求的整個生命周期中傳遞這個上下文對象。如此,我們就可以在請求結束時,及時釋放所有相關的資源。
  • 傳遞取消信號:context包提供了取消信號的傳遞機制。我們可以創建一個可以取消的上下文對象,并在需要取消操作時調用取消函數,通知所有相關的goroutine取消操作。當然這不是自動發生的,還需要我們編寫代碼進行判斷。
  • 設置超時時間:context包還提供了超時控制的機制。我們可以為操作設置超時時間,并在操作超時后自動取消操作。
  • 傳遞和共享數據:context包還提供了一種安全的方式在不同的goroutine之間傳遞和共享上下文信息。我們可以將一些關鍵數據存儲在上下文對象中,并在不同的函數調用中傳遞這個上下文對象,從而實現數據的安全共享。

context包的使用方法

HTTP請求處理中context應用

讓我們先通過一個例子來感受下 context 包的強大能力。n3C28資訊網——每日最新資訊28at.com

在Go的net/http包中,每個HTTP請求都會自動攜帶一個context。我們可以通過req.Context()方法獲取這個context,并在處理請求時使用它。以下是一個簡單的示例。n3C28資訊網——每日最新資訊28at.com

package mainimport (	"context"	"fmt"	"log"	"net/http"	"os"	"time")// 定義一個key類型,用于在context中存儲和檢索數據type key stringconst (	userIDKey key = "userID")// 定義一個向控制臺輸出日志的loggervar logger = log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)func main() {	http.HandleFunc("/hello", helloHandler)	http.ListenAndServe(":8080", nil)}func helloHandler(w http.ResponseWriter, req *http.Request) {	// 設置請求的超時為5秒	ctx, cancel := context.WithTimeout(req.Context(), 5*time.Second)	defer cancel()	// 在context中存儲一些共享數據,例如用戶ID	ctx = context.WithValue(ctx, userIDKey, "12345")	// 模擬一些工作,將在goroutine中運行,通過channel通知完成	done := make(chan struct{})	go func() {    // 從context取出用戶ID,記錄到日志中		userID := ctx.Value(userIDKey).(string)		logger.Println("開始處理:", userID)		time.Sleep(3 * time.Second) // 模擬耗時操作		close(done)	}()  // 通過select跟蹤context超時或者工作完成	select {	case <-ctx.Done():		// 請求被取消或超時		http.Error(w, "Request canceled or timed out", http.StatusRequestTimeout)	case <-done:		// 操作完成,從context中取出用戶ID,返回給調用方		userID := ctx.Value(userIDKey).(string)		fmt.Fprintf(w, "Hello, User ID: %s!/n", userID)	}}

在這個示例中,我們在HTTP處理器中使用 context.WithTimeout 設置了一個5秒的超時。如果請求在5秒內沒有完成,context將自動取消,處理器會返回一個超時錯誤響應。如果操作在5秒內完成,則返回正常的響應。n3C28資訊網——每日最新資訊28at.com

在這個例子中,我們還使用了 context 來共享數據,在創建超時context之后,我們使用 context.WithValue 在context 中存儲了用戶ID。n3C28資訊網——每日最新資訊28at.com

ctx = context.WithValue(ctx, userIDKey, "12345")

在處理具體的工作時,我們使用 ctx.Value 從context中檢索共享數據,打印正在處理的用戶:n3C28資訊網——每日最新資訊28at.com

userID := ctx.Value(userIDKey).(string)logger.Println("開始處理:", userID)

在完成后,我們還是使用ctx.Value從context中檢索共享數據,并將其包含在響應中:n3C28資訊網——每日最新資訊28at.com

userID := ctx.Value(userIDKey).(string)fmt.Fprintf(w, "Hello, User ID: %s!/n", userID)

基本的context用法

創建 context

在Go語言中,創建一個context對象是使用context包的第一步。n3C28資訊網——每日最新資訊28at.com

在上邊的例子中,我們從http請求中獲取了一個context,其實我們也完全可以自己創建一個新的context,有兩種基本方法:n3C28資訊網——每日最新資訊28at.com

  • context.Background()

context.Background()返回一個空的context對象,通常用于整個應用程序的頂級context,或者在不確定應該使用哪個context的情況下使用。它是一個常見的根context,所有的派生context都會基于它。n3C28資訊網——每日最新資訊28at.com

  • context.TODO()

context.TODO()與context.Background()類似,但通常用于你還不確定要使用哪個context,或者代碼還在開發過程中,未來可能會被替換為更具體的context。n3C28資訊網——每日最新資訊28at.com

傳遞context

我們可以在內嵌函數中直接使用有效范圍之內的 contex t實例,不過更常見的傳遞方法是通過函數參數。n3C28資訊網——每日最新資訊28at.com

在Go語言中,context對象通常作為函數的第一個參數進行傳遞。這種方式確保了context在整個調用鏈中被正確傳遞和使用。代碼如下:n3C28資訊網——每日最新資訊28at.com

func doSomething(ctx context.Context) {    // 在函數內部使用context}func main() {    ctx := context.Background()    doSomething(ctx)}

取消context

context.WithCancel() 函數返回一個派生的context和一個取消函數。調用取消函數會取消這個派生的context,并通知所有使用這個context的goroutine進行清理操作。示例代碼如下:n3C28資訊網——每日最新資訊28at.com

ctx, cancel := context.WithCancel(context.Background())go func() {    // 模擬一些工作    time.Sleep(2 * time.Second)    // 取消context    cancel()}()select {case <-ctx.Done():    fmt.Println("操作被取消")}

設置超時

上邊http服務端處理的例子中我們已經提供了一種設置context超時的方法,另外還有一個設置context超時的方法:context.WithDeadline(),這個函數函數類似于context.WithTimeout(),但它允許你指定一個具體的時間點作為截止時間。代碼示例如下:n3C28資訊網——每日最新資訊28at.com

deadline := time.Now().Add(3 * time.Second)ctx, cancel := context.WithDeadline(context.Background(), deadline)defer cancel()  // 確保在不再需要時取消contextselect {case <-ctx.Done():    fmt.Println("操作在截止時間前未完成")}

context的最佳實踐

合理設置超時時間

超時時間設置的過長,請求都等著,可能會消耗過多的計算資源;設置的太小,頻繁超時,又會給用戶帶來不好的使用體驗。以下是一些最佳實踐:n3C28資訊網——每日最新資訊28at.com

  1. 根據業務需求設置超時:不同的業務場景對響應時間的要求不同。根據具體業務需求來設置超時時間,例如用戶請求的超時可以設置得較短,而后臺批量處理任務的超時可以設置得較長。
  2. 逐層縮短超時:在多層級服務調用中,通常應該逐層縮短超時時間。比如,頂層請求的超時時間為10秒,調用的子服務可以設置為8秒,再調用的子服務可以設置為6秒,以確保在超時前有足夠的時間處理和傳遞錯誤。
  3. 考慮網絡延遲和重試機制:在分布式系統中,網絡延遲和重試機制會影響實際的處理時間。設置超時時應考慮這些因素,避免超時時間過短導致頻繁的重試。

避免context的濫用

context包的主要目的是在請求的生命周期中傳遞取消信號、超時和共享數據,不要傳遞過多的業務數據,以下是一些建議:n3C28資訊網——每日最新資訊28at.com

  1. 不將context用于傳遞業務數據:context應該只用于傳遞請求的控制信息(如取消信號、超時和trace信息),不應該用于傳遞業務數據。
  2. 不將context存儲在結構體中:context是臨時性的,不應該存儲在結構體中以避免內存泄漏和不必要的復雜性。
  3. 及時取消context:使用context.WithCancel、context.WithTimeout或context.WithDeadline創建的context應該及時調用取消函數,以釋放資源。
  4. 避免頻繁創建context:創建和取消context本身的開銷相對較小,但頻繁的創建和取消操作仍然會對性能產生一定影響,特別是在高并發場景下。在設計系統時,盡量減少不必要的context創建操作,可以復用已有的context,避免在每個函數調用中都創建新的context。

有的同學可能會有疑問:context.WithTimeout 或 context.WithDeadline 創建的context等著超時或者正常處理完成不就可以了嗎?n3C28資訊網——每日最新資訊28at.com

其實 context.WithTimeout 和 context.WithDeadline,這兩個函數內部也是通過 WithCancel 實現的,因此也會返回一個 cancel 函數。盡管當超時或截止日期到達時,context會自動“過期”,不過調用 cancel 函數仍然是一個好習慣,因為它可以立即停止任何依賴于此上下文的正在進行的操作,而不僅僅等待它們自然發現上下文已過期。n3C28資訊網——每日最新資訊28at.com

與其他包的結合使用

我們不僅可以在自己編寫的代碼中使用context,很多標準庫也提供了context的支持,這樣可以更好的管理請求和資源。上邊的示例中已經演示了與net/http包結合,我們再看下database/sql的例子:n3C28資訊網——每日最新資訊28at.com

package mainimport (    "context"    "database/sql"    "log"    "time"    _ "github.com/go-sql-driver/mysql")func main() {    db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/dbname")    if err != nil {        log.Fatal(err)    }    defer db.Close()    // 創建一個帶超時的 context    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)    defer cancel()    // 查詢數據庫時,傳入這個context    rows, err := db.QueryContext(ctx, "SELECT * FROM users")    if err != nil {        log.Println("Query error:", err)        return    }    defer rows.Close()    for rows.Next() {        var id int        var name string        if err := rows.Scan(&id, &name); err != nil {            log.Println("Scan error:", err)            return        }        log.Printf("User: %d, Name: %s/n", id, name)    }    if err := rows.Err(); err != nil {        log.Println("Rows error:", err)    }}

通過結合使用context包和其他標準庫,我們就可以更好地管理每個請求的生命周期和使用的各種資源,提高整個系統的穩定性和可維護性。n3C28資訊網——每日最新資訊28at.com


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

本文鏈接:http://m.www897cc.com/showinfo-26-92097-0.htmlGo語言中的context包到底解決了啥問題?

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

上一篇: 聯發科天璣 9300 系列亮相 COMPUTEX 2024,加速生成式 AI 手機時代到來

下一篇: Genai技術棧架構指南—十個工具,你知道哪個?

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
久久精品视频一| 久久亚洲一区二区| 欧美另类一区| 欧美精品日韩综合在线| 久久久综合视频| 久久蜜桃资源一区二区老牛 | 伊人天天综合| 欧美视频在线看| 欧美日韩成人综合在线一区二区 | 国产精品爱久久久久久久| 一本到高清视频免费精品| 国产欧美精品一区| 国产精品久久久久久久久借妻| 欧美日韩亚洲三区| 国产精品永久免费在线| 在线成人h网| 亚洲欧洲av一区二区| 久久综合中文字幕| 国产精品伦一区| 日韩视频一区二区在线观看 | 亚洲娇小video精品| 这里是久久伊人| 老司机精品视频网站| 国产麻豆精品视频| 一区二区三区不卡视频在线观看 | 亚洲桃色在线一区| 欧美福利在线观看| 在线精品一区二区| 久久精品亚洲乱码伦伦中文| 欧美日韩在线观看视频| 91久久久在线| 美日韩精品视频| 狠狠色伊人亚洲综合成人| 性欧美8khd高清极品| 国产精品卡一卡二卡三| 一本色道久久| 欧美色一级片| 亚洲午夜激情网站| 欧美日一区二区在线观看 | 亚洲视频在线免费观看| 欧美精品一区二区三区在线看午夜 | 久久精品91| 国内伊人久久久久久网站视频 | 亚洲一区二区三区高清| 欧美网站在线| 亚洲一区二区高清| 国产精品一区二区三区观看| 亚洲欧美日韩视频二区| 国产精品jvid在线观看蜜臀| 亚洲尤物在线| 国产日韩欧美二区| 欧美精品日韩三级| 亚洲精品一区二区三区99| 欧美国产一区二区| 欧美一区二区三区视频| 一本色道久久综合亚洲精品高清 | 亚洲日本va午夜在线电影 | 国产精品日韩在线一区| 久久精品最新地址| 亚洲色图在线视频| 亚洲国产精品va在线看黑人 | 日韩视频在线观看免费| 蜜臀a∨国产成人精品| 在线观看国产欧美| 欧美电影免费观看大全| 亚洲国产欧美日韩另类综合| 久久精品一本久久99精品| 国产午夜精品久久久久久免费视 | 欧美日韩精品在线观看| 91久久线看在观草草青青| 欧美日韩精品三区| 欧美一二三视频| 国产亚洲精品久久久| 久久亚洲精品一区二区| 国产午夜精品美女视频明星a级 | 欧美黄色免费网站| 一区免费观看| 在线观看亚洲视频啊啊啊啊| 欧美一区国产二区| 国产欧美日韩不卡免费| 日韩视频中文| 久久成人免费| 国产精品国产三级国产普通话99 | 亚洲高清免费| 欧美日韩综合| 免费在线国产精品| 欧美一区二区精品久久911| 99re热这里只有精品视频| 激情综合亚洲| 国产亚洲人成网站在线观看| 欧美无乱码久久久免费午夜一区| 欧美大胆成人| 欧美11—12娇小xxxx| 老司机成人网| 免费成人性网站| 免费精品99久久国产综合精品| 欧美一区二区日韩| 欧美一区二区视频在线观看| 亚洲女同在线| 香蕉久久夜色精品国产| 性久久久久久| 久久另类ts人妖一区二区| 久久久久久有精品国产| 久久综合中文字幕| 免费欧美电影| 欧美日韩不卡合集视频| 欧美日韩成人综合天天影院| 欧美午夜精品理论片a级按摩| 欧美日韩亚洲国产一区| 欧美午夜电影完整版| 国产精品免费观看视频| 国产精品丝袜白浆摸在线| 国产日韩欧美综合在线| 黄色欧美成人| 亚洲乱亚洲高清| 亚洲素人一区二区| 久久国产精品一区二区| 美女精品国产| 国产精品盗摄久久久| 国产一区二区av| 亚洲区在线播放| 亚洲欧美在线免费观看| 久久婷婷av| 欧美日韩亚洲视频一区| 国产亚洲欧美日韩精品| 亚洲激情女人| 欧美一级大片在线观看| 欧美成人精品不卡视频在线观看| 欧美三级在线视频| 红桃视频国产精品| 99视频一区二区| 久久久国产精品一区二区中文| 欧美久久电影| 黄色成人在线网址| 亚洲小说区图片区| 欧美gay视频激情| 国产日韩欧美亚洲| 亚洲免费电影在线观看| 欧美主播一区二区三区美女 久久精品人| 久久综合激情| 国产视频精品网| 亚洲性视频网址| 欧美另类人妖| 亚洲黄色免费网站| 久久在线免费观看| 国产一区二区视频在线观看| 亚洲人成网站精品片在线观看 | 久久久久久夜| 国产精品综合不卡av| 亚洲一级特黄| 国产欧亚日韩视频| 久久天堂成人| 亚洲电影天堂av| 欧美日韩国产天堂| 香蕉久久一区二区不卡无毒影院 | 国产精品区一区二区三区| 亚洲理论电影网| 久久激情视频久久| 国产精品女人久久久久久| 中文av字幕一区| 欧美激情第10页| 亚洲国产成人一区| 欧美日本高清| 日韩视频在线观看| 男女精品网站| 99视频在线精品国自产拍免费观看| 久久精品女人天堂| 国产真实精品久久二三区| 久久精品视频导航| 国产一区二区三区免费不卡| 久久人人精品| 亚洲黄色有码视频| 欧美调教视频| 午夜精品一区二区三区在线| 国产亚洲视频在线观看| 99国产一区| 欧美日韩国产精品一区| 亚洲精品无人区| 久久精品夜色噜噜亚洲a∨| 国产精品高潮呻吟久久av黑人| 久久精彩视频| 亚洲日本黄色| 欧美~级网站不卡| 国内久久精品| 亚洲午夜国产一区99re久久 | 欧美二区乱c少妇| 欧美激情一区在线观看| 国产一区二区日韩精品| 亚洲欧洲日产国产综合网| 校园激情久久| 欧美成熟视频| 狠狠色狠狠色综合日日五| 国内精品久久久久久久果冻传媒| 亚洲一级高清| 欧美黄网免费在线观看| 99精品视频免费观看视频| 欧美日韩国产综合网| 亚洲欧美三级伦理| 在线精品视频在线观看高清| 欧美图区在线视频| 免费在线日韩av| 久久久久久久久蜜桃| 亚洲欧美日韩精品久久久久| 91久久久久久久久|