英文:
How to detect a timeout occurred using Go's WithTimeout
问题
我有以下的Go代码:
func MyFunc(ctx context.Context, cfg *Config) (packedevent []byte, err error, publishEvent bool) {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, cfg.ScanTimeout)
defer cancel()
event := GetEvent(ctx, cfg)
packedevent, err = PackEvent(event)
publishEvent = shouldSendToIoT(event)
return
}
我想使用context.WithTimeout
使这个函数超时。
我还没有找到如何在超时发生时设置err
的方法。
我查看了Go文档中的示例(https://pkg.go.dev/context#example-WithTimeout),但我并没有真正理解它。<-ctx.Done()
这种情况是否总是表示超时已经发生?这个示例似乎暗示相反-<-ctx.Done()
表示代码已经完成而没有超时。
我想要澄清一下如何检测使用context.WithTimeout
运行的代码是否已经超时。
此外,我想了解在我的代码中应该在哪里检查超时是否发生。我最初的想法是将此检查放在函数的末尾,但这样是否太晚了?
英文:
I have the following Go code:
func MyFunc(ctx context.Context, cfg *Config) (packedevent []byte, err error, publishEvent bool) {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, cfg.ScanTimeout)
defer cancel()
event := GetEvent(ctx, cfg)
packedevent, err = PackEvent(event)
publishEvent = shouldSendToIoT(event)
return
}
I am trying to cause this function to timeout using context.WithTimeout
.
What I have not been able to figure out is how to set err
if the timeout occurs.
I looked at the example in the Go docs but I did not really understand it. Does the <-ctx.Done()
case always mean that the timeout was reached? This example seems to suggest the opposite - that <-ctx.Done()
means the code ran to completion without timing out.
I am looking for clarification on how to detect when code run with context.WithTimeout
has or has not timed out.
Additionally, I would like to understand where in my code I should check if the timeout occurred. My first thought was to put this check at the end of the function, but would that be putting the check too late?
答案1
得分: 2
要检测上下文是否超时,请检查ctx.Error()
。如果错误是context.Canceled
,则表示上下文已使用cancel()
函数取消。如果是context.DeadlineExceeded
,则表示已超时。
要检查上下文是否已取消或超时,请使用以下代码:
select {
case <-ctx.Done():
// 已取消或已超时
default:
// 为了避免阻塞select语句
}
英文:
To detect if the context has timed out, check ctx.Error()
. If the error is context.Canceled
, then the context has been canceled using the cancel()
function. If it is context.DeadlineExceeded
, then it timed out.
To check if the context has been canceled or timed out, use:
select {
case <-ctx.Done():
// canceled or timed out
default:
// So the select will not block
}
答案2
得分: 1
ctx.Done()
在超时达到或调用取消函数时触发。
根据文档:
> Done返回一个通道,当代表此上下文的工作应该被取消时,该通道将被关闭。
英文:
ctx.Done()
fires when the timeout is reached or the cancel func is called.
> Done returns a channel that's closed when work done on behalf of this context should be canceled.
答案3
得分: 0
你可以尝试这段代码:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
defer cancel()
for {
select {
case <-ctx.Done():
fmt.Println(ctx.Err())
return
default:
fmt.Println("做一些事情")
time.Sleep(time.Second)
}
}
}
输出应该是:
做一些事情
做一些事情
上下文超时
英文:
You can try this code:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
defer cancel()
for {
select {
case <-ctx.Done():
fmt.Println(ctx.Err())
return
default:
fmt.Println("do something")
time.Sleep(time.Second)
}
}
}
The output should be:
do something
do something
context deadline exceeded
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论