首頁 >後端開發 >Golang >深入介紹Golang context的用法

深入介紹Golang context的用法

PHPz
PHPz原創
2023-04-11 09:14:041262瀏覽

Golang是一門強大的程式語言,具有高效性和簡潔性,目前正在快速發展中。在編寫Go程式碼時,每個函數的輸入和輸出參數都有自己的生命週期。當多個Goroutine同時運行時,我們可能需要管理上下文以確保程式的正確性,這就是Golang context的作用。在本文中,我們將介紹Golang context的用法。

一、Golang Context的概念

Golang Context是一個包含請求範圍內相關值的物件。該物件可在各個函數之間傳遞,並提供了取消操作的支援。例如,在處理Http請求時,我們可以使用context套件傳遞Http請求作為參數,從而獲得請求相關的上下文。

Golang Context的結構體定義如下:

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key interface{}) interface{}
}

上述結構體的定義中包含了Deadline、Done、Err和Value方法,下面我們將逐一介紹它們的作用。

二、Golang Context的使用

  1. Deadline方法

Deadline方法傳回一個時間和一個布林值。當context被取消或到達其deadline時,context會傳回這個時間和一個true的布林值,否則回傳false。有些context是沒有deadline的,這時Deadline方法會回傳false。

func main() {
    ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*5))
    defer cancel()
    
    select {
    case <-time.After(3 * time.Second):
        fmt.Println("等待了3秒钟")
    case <-ctx.Done():
        fmt.Println(ctx.Err())
    }
}

在上述程式碼中,首先我們建立了一個帶有Deadline的Context,其截止時間為當前時間後5秒。然後我們使用select語句等待3秒鐘,這時我們會發現程式仍然在等待,這是因為等待時間沒有超過Deadline。最後,當超過Deadline的時候,程式會因為ctx.Done()的回傳值而結束運作。

  1. Done方法

Done方法傳回一個只讀的channel,當context被取消或到達deadline時,這個channel會被關閉。因此,我們可以在我們的程式碼中使用select語句和Done方法來監控Context的狀態。

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    go func(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println(ctx.Err())
                return
            default:
                fmt.Println("goroutine正在运行中...")
                time.Sleep(1 * time.Second)
            }
        }
    }(ctx)

    // 模拟耗时操作
    time.Sleep(5 * time.Second)
    cancel() // 取消Context
    time.Sleep(3 * time.Second)
    fmt.Println("main函数执行结束")
}

上述程式碼中,我們使用WithCancel和cancel函數開始和結束Context,並在一個goroutine中定期列印日誌,直到Context被取消。同時,我們使用Sleep模擬一個耗時操作。目前函數在5秒後呼叫cancel函數,終止了Context,整個程式也因此結束。

  1. Err方法

Err方法回傳Context被取消的原因。對於已經取消的Context,該方法會傳回一個非空的錯誤值。如果Context沒有被取消,Err方法會回傳nil。

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    go func(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println(ctx.Err())
                return
            default:
                fmt.Println("goroutine正在运行中...")
                time.Sleep(1 * time.Second)
            }
        }
    }(ctx)

    // 模拟耗时操作
    time.Sleep(5 * time.Second)
    cancel() // 取消Context
    time.Sleep(3 * time.Second)
    fmt.Println("main函数执行结束")
}

上述程式碼中,在goroutine中使用了Err方法,該方法回傳了被取消的原因。最終,我們在主函數中列印 "main函數執行結束"。

  1. Value方法

Value方法傳回與Context關聯的值,該值是一個interface{}類型的物件。可以在Context中設定任何類型的值,並且在之後的操作中使用Value方法取得該值。

type authKey string
func main() {
    ctx := context.WithValue(context.Background(), authKey("token"), "123456")
    fmt.Println(ctx.Value(authKey("token"))) // 打印"123456"
}

在上述程式碼中,我們使用WithValue方法將字串類型的值與Context關聯起來,並使用Value方法取得該值。

三、總結

Golang Context是處理並發程式碼中很重要的一部分。透過在各個函數之間傳遞Context,我們可以管理程式碼中的生命週期,同時也可以透過Done、Err和Value等方法來監控Context的狀態。掌握Golang Context的使用方法可以提高程式碼的品質和並發能力。

以上是深入介紹Golang context的用法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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