func handleRequest(w http.ResponseWriter, r *http.Request) { reqID := uuid.New().String() ctx := context.WithValue(r.Context(), "requestID", reqID) go doBackgroundWork(ctx) // rest of request handling code ... } func doBackgroundWork(ctx context.Context) { reqID := ctx.Value("requestID").(string) // use reqID to log or track the work being done ... }
func handleRequest(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(r.Context(), time.Second * 10) defer cancel() // ensure ctx cancellation when request handling is done go doExpensiveWork(ctx) // rest of request handling code ... } func doExpensiveWork(ctx context.Context) { for { select { case <- ctx.Done(): // cancellation signal received return default: // do some expensive computation ... } } }In both examples, the context is created using the `context.WithValue` or `context.WithTimeout` functions, and passed around down the call chain as an argument to functions that need access to the request-scoped value or cancellation signal.