我有这个简单的代码,我尝试检查请求是否被取消。但令人惊讶的是,它在第1.9版中打印false
而不是true
。
我想知道检查它的正确方法是什么?
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
}
答案 0 :(得分:9)
您可以检查上下文的错误:
package main
import (
"context"
"fmt"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
fmt.Println(ctx.Err())
cancel()
fmt.Println(ctx.Err())
}
打印
<nil>
context canceled
答案 1 :(得分:4)
在Go 1.13+中最干净的方法是使用新的errors.Is
函数。
// Create a context that is already canceled
ctx, cancel := context.WithCancel(context.Background())
cancel()
// Create the request with it
r, _ := http.NewRequest("GET", "http://example.com", nil)
r = r.WithContext(ctx)
// 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))
答案 2 :(得分:1)
您可以检查上下文是否已被取消。
go func() {
for {
if <-ctx.Done() {
log.Println(ctx.Err() == context.Canceled)
break
}
}
}()
取消ctx时会触发if语句。 循环是无限的(如果不调用break)并且将与其余代码并行运行。