首页 >后端开发 >Golang >如何可靠地检查 Go 中的请求取消错误,即使它已被另一个错误包裹?

如何可靠地检查 Go 中的请求取消错误,即使它已被另一个错误包裹?

DDD
DDD原创
2024-11-08 04:08:01307浏览

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