首頁  >  文章  >  後端開發  >  如何可靠地檢查 Go 中的請求取消錯誤,即使它已被另一個錯誤包裹?

如何可靠地檢查 Go 中的請求取消錯誤,即使它已被另一個錯誤包裹?

DDD
DDD原創
2024-11-08 04:08:01254瀏覽

How do I reliably check for a request cancellation error in Go, even if it has been wrapped by another error?

在 Go 中檢查請求取消

在 Go 中,確定請求是否已被取消可能是一個挑戰。考慮以下程式碼:

package main

import (
    "context"
    "log"
    "net/http"
)

func main() {
    r, _ := http.NewRequest("GET", "http://example.com", nil)
    ctx, cancel := context.WithCancel(context.Background())
    r = r.WithContext(ctx)
    ch := make(chan bool)
    go func() {
        _, err := http.DefaultClient.Do(r)
        log.Println(err == context.Canceled)
        ch <- true
    }()
    cancel()
    <-ch
}

令人驚訝的是,即使請求應該被取消,此程式碼在 Go 1.9 中也會列印 false。

正確的方法

在更新的版本中在Go中,檢查取消的更好方法是使用Go 1.13中引入的errors.Is函數。這是程式碼的更新版本:

import (
    "context"
    "errors"
    "log"
    "net/http"
)

func main() {
    // Create a context that is already canceled
    ctx, cancel := context.WithCancel(context.Background())
    cancel()

    // Create the request with it
    r, _ := http.NewRequestWithContext(ctx, "GET", "http://example.com", nil)

    // Do it, it will immediately fail because the context is canceled.
    _, err := http.DefaultClient.Do(r)
    log.Println(err) // Get http://example.com: context canceled

    // This prints false, because the http client wraps the context.Canceled
    // error into another one with extra information.
    log.Println(err == context.Canceled)

    // This prints true, because errors.Is checks all the errors in the wrap chain,
    // and returns true if any of them matches.
    log.Println(errors.Is(err, context.Canceled))
}

透過使用errors.Is,我們可以可靠地檢查底層錯誤是否是上下文取消錯誤,即使它已被另一個錯誤包裝。 error.Is 函數將遍歷整個錯誤鏈,如果其中任何一個與給定的錯誤類型匹配,則傳回 true。

以上是如何可靠地檢查 Go 中的請求取消錯誤,即使它已被另一個錯誤包裹?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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