首頁 後端開發 Golang 深入了解Go Context的用法

深入了解Go Context的用法

Apr 05, 2023 am 09:10 AM

Go語言中的Context,非常好用,幾乎所有的Go程式都使用它來傳遞請求範圍的值。它是一個輕量級的對象,允許跨API邊界傳遞請求範圍的值,包括取消訊號、截止日期和請求ID等。

在本文中,我們將深入了解Go Context的用法,以了解它的優點及如何使用它來提高應用程式的效能和健全性。

什麼是Go Context?

Go Context是Go語言中的一個標準函式庫,用來管理請求範圍的值。它為應用程式提供一個輕量級的,且具有傳遞性的方法,用於在 goroutine 之間傳遞請求的變數。它主要用於傳遞取消請求、逾時限制、追蹤日誌、請求上下文以及請求資料等。

與其他程式語言中的 Context 不同,Go Context 具有一些非常特殊的性質:

  • 它是線程安全的。
  • 它的值可以跨 goroutine 傳遞。
  • 它可以取消或逾時,以防止長時間運行或無法停止的操作。
  • 它還可以用於分離請求取消和實際操作取消。

使用場景

Go Context是非常通用的工具,可以用於不同場景下的應用程序,其中一些場景包括:

  1. Web應用程式

Web應用程式是最常見的使用場景之一。它可以輕鬆地管理處理 HTTP 請求所需的上下文和請求特定的元資料。在HTTP請求處理期間,Context 被用於跨 handler 傳遞請求ID,請求逾時限制,取消訊號等。例如,Context 在處理 Websocket 連線時用於追蹤會話狀態。

  1. 後台服務應用程式

後台服務應用程式可能需要遍歷多個API 以為外部系統提供數據,Context 在這種應用程式中被用於完成goroutine更有效率的終止,是這種應用程式的最佳選擇。您可以使用 Context WithCancel 標準函數來實現這一點。如果所有的 goroutine 都使用這個 Context,那麼只需要回調一次即可停止所有訂閱並清理資源。

  1. 資料庫和檔案操作

Go Context 是處理大型檔案和 DB 作業的理想工具,因為這些操作可能會耗費大量的資源和 I/O。在這種情況下,Context 用於取消操作,以避免失誤和執行時間錯誤。

  1. 分散式應用程式

在微服務架構中,Context 被廣泛用於從 API 傳遞請求範圍的資訊到各個服務的呼叫鏈。在這種情況下,追蹤追蹤ID儲存在 Context 中,並在連接多個服務時傳遞。這使得整個請求線路的追蹤變得容易。

Context的用法

現在我們已經了解了 Go Context 的基礎知識,接下來我們將探討如何使用它來管理請求範圍的值。

  1. 建立一個Context

在 Go 語言中,您可以使用 context.Background() 來建立一個空的頂層 context。這個 context 是全域獨立的,不包含任何值。

ctx := context.Background()
登入後複製

您也可以使用 WithValue() 函數來建立一個帶有值的 context。例如,您可以建立一個 HTTP 請求處理的 context 帶有請求資料和逾時限制。

ctx := context.WithValue(
        context.Background(),
        "requestId",
        uuid.New())
登入後複製

ctx.Value() 函數使用這個 context 來取得 context 的值。在下面的範例中,我們可以透過請求唯一識別碼來取得 Context 資訊。

requestId, ok := ctx.Value("requestId").(value string)
登入後複製
  1. 逾時訊號

使用 context.WithDeadline 或 context.WithTimeout 函數,您也可以將逾時訊號應用於 context,以避免長時間運行的過程。

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
登入後複製

cancel() 函數被用來標記 C​​ontext 的取消狀態。在逾時事件發生時,Context 將自動取消。

select {
case <-timeOutCtx.Done():
         if err := timeOutCtx.Err(); err != nil {
                   fmt.Println("Time out due to: ", err)
         }
case <-time.After(5 * time.Second):
       fmt.Println("Hooray! Request done within 5 sec")
}
登入後複製

在這個例子中,我們建立一個10秒的超時 Context。 select 語句等待兩個 channel 上的動作。 Done() 方法,當 Context 取消或逾時時,將發出訊號。

我們透過計時器 channel 發送短訊息,等待 5 秒。因為我們 context.WithTimeout() 函數的第二個參數是 10 秒,所以應該只有選擇語句中的第一條路線被執行。

  1. Context可取消

Context 在長時間的運作過程中使用,可以使用取消訊號的一個特性,以避免對系統產生意外的負載。

在下面的程式碼片段中,我們將使用 context.WithCancel() 建立一個 Context,然後使用 cancel() 函數來標記 C​​ontext 的取消狀態。給定的 goroutine 如果在 Context 取消之前完成,則透過 Done() 方法發送它的 完成訊號 。

ctx, cancel := context.WithCancel(context.Background())

go func(ctx context.Context) {
      select {
             case <-ctx.Done():
                 fmt.Println("Exiting goroutine")
                 return
             default:
                  fmt.Println("Processing...")
       }
}(ctx)

// Exit after 5 sec
time.AfterFunc(5*time.Second, cancel)
登入後複製

在這裡,我們在 goroutine 中使用 Done() 和預設分支。如果 Context 取消或逾時,Done() 方法將傳回一個訊號,並呼叫 cancel() 函數來取消 goroutine 的運行。

在主函數中,我們使用 time.AfterFunc() 函數呼叫這個 Context 的取消() 函數來標記 C​​ontext 的取消狀態。這將在 5 秒鐘後觸發 goroutine 取消操作。

  1. Context超时和取消

在处理请求的时间,我们通常需要确保 goroutine 不会无限期地等待,而需要在可接受的时间范围内执行操作。

在下面的代码段中,我们将使用 context.WithTimeout() 函数创建一个带有 5 秒超时限制的 Context。

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

select {
    case <-time.After(5 * time.Second):
       fmt.Println("Request completed")
    case <-ctx.Done():
         fmt.Println("Exit due to: ", ctx.Err())
}
登入後複製

我们也使用了 cancel() 函数,确保 Context 被取消时自动触发。

为了模拟一个长时间的操作,我们使用 time.After(channel)。 当 goroutine 执行时间超过 2 秒时,Context 始终会被取消。 select 语句通过检查两个 channel 的操作结果而“安全地”退出。

总结

在 Go 语言中,Context 是通用工具,用于管理请求范围的数据。它提供了一种非常强大,灵活的方法,以跨 API 边界传递请求范围的值,如取消信号、截止日期、请求 ID 等。

在本文中,我们深入探讨了 Go Context 的一些实际用例,并讨论了一些最佳实践,以优化应用程序的可维护性和性能。

随着应用程序和网络的规模增长,Context 的正确使用和管理变得非常重要。如果用得当,它可以提高应用程序的健壮性和性能,从而确保进行细粒度的请求管理。

以上是深入了解Go Context的用法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Debian OpenSSL有哪些漏洞 Debian OpenSSL有哪些漏洞 Apr 02, 2025 am 07:30 AM

OpenSSL,作為廣泛應用於安全通信的開源庫,提供了加密算法、密鑰和證書管理等功能。然而,其歷史版本中存在一些已知安全漏洞,其中一些危害極大。本文將重點介紹Debian系統中OpenSSL的常見漏洞及應對措施。 DebianOpenSSL已知漏洞:OpenSSL曾出現過多個嚴重漏洞,例如:心臟出血漏洞(CVE-2014-0160):該漏洞影響OpenSSL1.0.1至1.0.1f以及1.0.2至1.0.2beta版本。攻擊者可利用此漏洞未經授權讀取服務器上的敏感信息,包括加密密鑰等。

從前端轉型後端開發,學習Java還是Golang更有前景? 從前端轉型後端開發,學習Java還是Golang更有前景? Apr 02, 2025 am 09:12 AM

後端學習路徑:從前端轉型到後端的探索之旅作為一名從前端開發轉型的後端初學者,你已經有了nodejs的基礎,...

Go的爬蟲Colly中Queue線程的問題是什麼? Go的爬蟲Colly中Queue線程的問題是什麼? Apr 02, 2025 pm 02:09 PM

Go爬蟲Colly中的Queue線程問題探討在使用Go語言的Colly爬蟲庫時,開發者常常會遇到關於線程和請求隊列的問題。 �...

Go語言中用於浮點數運算的庫有哪些? Go語言中用於浮點數運算的庫有哪些? Apr 02, 2025 pm 02:06 PM

Go語言中用於浮點數運算的庫介紹在Go語言(也稱為Golang)中,進行浮點數的加減乘除運算時,如何確保精度是�...

Beego ORM中如何指定模型關聯的數據庫? Beego ORM中如何指定模型關聯的數據庫? Apr 02, 2025 pm 03:54 PM

在BeegoORM框架下,如何指定模型關聯的數據庫?許多Beego項目需要同時操作多個數據庫。當使用Beego...

在 Go 語言中,為什麼使用 Println 和 string() 函數打印字符串會出現不同的效果? 在 Go 語言中,為什麼使用 Println 和 string() 函數打印字符串會出現不同的效果? Apr 02, 2025 pm 02:03 PM

Go語言中字符串打印的區別:使用Println與string()函數的效果差異在Go...

在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? 在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? Apr 02, 2025 pm 04:54 PM

Go語言中使用RedisStream實現消息隊列時類型轉換問題在使用Go語言與Redis...

GoLand中自定義結構體標籤不顯示怎麼辦? GoLand中自定義結構體標籤不顯示怎麼辦? Apr 02, 2025 pm 05:09 PM

GoLand中自定義結構體標籤不顯示怎麼辦?在使用GoLand進行Go語言開發時,很多開發者會遇到自定義結構體標籤在�...

See all articles