That context then has a .Done() method that returns a channel; when a value is written to that channel, whatever functions are using that context are expected to stop themselves at the soonest point that makes sense to them.
Typically this is done inside a for loop in long-running processes. I.e. for something that copies, it looks like
for {
select {
case <-ctx.Done():
// we should stop and return a timeout error or something
default:
// copy some number of bytes, or check if a network call is done
}
}
It does require all of the involved functions to implement support for this, though I think most things do at this point. I wouldn't call a library high quality unless it supports context.Context for long-running operations.It gives library authors the ability to determine at what points their code can be interrupted, run cleanup code as part of the timeout, etc.
> The best way I've found of doing this so far involves proceses: run the time-bound operation in an entirely separate process and terminate it early if necessary.
This doesn't handle remote resources cleanly, does it? E.g. if I were to lock a Postgres table for a query, and that query times out, will that correctly unlock the table and close the client? Or e.g. lock files? I'm sure some of that can be handled very carefully by managing it in the main process, but that seems error prone.