Search code examples
gotimeout

How to detect a timeout occurred using Go's 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?


Solution

  • 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
    }