在 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中文网其他相关文章!