context.WithTimeoutCause în Go

Ca WithTimeout și WithDeadline, dar la expirare context.Cause(ctx) returnează eroarea ta, nu doar DeadlineExceeded.

Sintaxă
func WithTimeoutCause(parent Context, timeout time.Duration, cause error) (Context, CancelFunc)
func WithDeadlineCause(parent Context, d time.Time, cause error) (Context, CancelFunc)

Ce face context.WithTimeoutCause

WithTimeoutCause(parinte, durata, motiv) creează un context cu limită de timp. Când limita expiră, ctx.Err() este context.DeadlineExceeded, iar context.Cause(ctx) returnează motiv. Așa afli care limită anume a expirat când ai mai multe (bază de date, serviciu de plăți, cache).

WithDeadlineCause face același lucru cu un moment fix în loc de durată. Funcția cancel returnată nu primește motiv; dacă anulezi tu manual, Cause va fi context.Canceled.

Parametri

Parametru Descriere
parent Contextul părinte.
timeout / d Durata, respectiv momentul limită.
cause Eroarea raportată de context.Cause la expirare.

Ce returnează

Contextul și funcția cancel.

Exemple

Exemplul 1: Care limită a expirat?

package main

import (
	"context"
	"errors"
	"fmt"
	"time"
)

var ErrPlataLenta = errors.New("serviciul de plăți nu a răspuns în 50ms")

func main() {
	ctx, cancel := context.WithTimeoutCause(context.Background(), 50*time.Millisecond, ErrPlataLenta)
	defer cancel()

	<-ctx.Done()
	fmt.Println("Err:  ", ctx.Err())
	fmt.Println("Cause:", context.Cause(ctx))
	fmt.Println("Este DeadlineExceeded:", errors.Is(ctx.Err(), context.DeadlineExceeded))
}

Rezultat

Err:   context deadline exceeded
Cause: serviciul de plăți nu a răspuns în 50ms
Este DeadlineExceeded: true

Exemplul 2: WithDeadlineCause cu termen trecut și anulare manuală

package main

import (
	"context"
	"errors"
	"fmt"
	"time"
)

func main() {
	termen := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
	ctx, cancel := context.WithDeadlineCause(context.Background(), termen,
		errors.New("înscrierile s-au închis la 1 ianuarie"))
	defer cancel()
	fmt.Println("Cause:", context.Cause(ctx))

	ctx2, cancel2 := context.WithTimeoutCause(context.Background(), time.Hour, errors.New("nu apare"))
	cancel2()
	fmt.Println("Anulat manual, Cause:", context.Cause(ctx2))
}

Rezultat

Cause: înscrierile s-au închis la 1 ianuarie
Anulat manual, Cause: context canceled

Greșeli frecvente

  • Aștepți ca motivul să apară și la anularea manuală cu cancel(). Motivul se folosește doar la expirarea timpului; pentru anulări manuale cu motiv folosește WithCancelCause.

Comenzi înrudite

  • context.WithTimeout: Creează un context care se anulează singur după durata dată; limita de timp standard pentru cereri și interogări.
  • context.WithDeadline: Creează un context care se anulează singur la un moment fix (ora limită), nu după o durată.
  • context.WithCancelCause: Ca WithCancel, dar cancel primește motivul anulării; context.Cause(ctx) returnează acel motiv.