time.After în Go

Returnează un canal care primește ora curentă după durata dată; folosit în select pentru limite de timp (timeout).

Sintaxă
func After(d Duration) <-chan Time

Ce face time.After

time.After(d) creează un temporizator și îți dă canalul lui. După durata d, pe canal sosește momentul expirării. Locul lui obișnuit este într-un select, alături de canalul care aduce rezultatul: dacă rezultatul vine primul îl folosești, dacă vine întâi semnalul de la time.After, ai depășit timpul.

Din Go 1.23 temporizatorul este eliberat de colectorul de memorie chiar dacă nimeni nu citește canalul, deci time.After în bucle nu mai pierde memorie. Dacă vrei totuși să oprești temporizatorul devreme, folosește time.NewTimer și Stop. Pentru operații care trebuie anulate în lanț (cereri HTTP, interogări), preferă context.WithTimeout.

Parametri

Parametru Descriere
d După cât timp sosește valoarea pe canal.

Ce returnează

Un canal doar pentru citire (<-chan time.Time).

Exemple

Exemplul 1: Limită de timp pentru un calcul

Canalul rezultat are buffer 1, ca goroutine-ul să poată scrie și să se termine chiar dacă nimeni nu mai citește.

package main

import (
	"fmt"
	"time"
)

func cauta(produs string, durata time.Duration) <-chan string {
	rezultat := make(chan string, 1)
	go func() {
		time.Sleep(durata) // simulăm o căutare lentă
		rezultat <- produs + ": 3 bucăți în stoc"
	}()
	return rezultat
}

func main() {
	select {
	case r := <-cauta("laptop", 50*time.Millisecond):
		fmt.Println("Găsit:", r)
	case <-time.After(500 * time.Millisecond):
		fmt.Println("Timpul a expirat")
	}

	select {
	case r := <-cauta("frigider", 2*time.Second):
		fmt.Println("Găsit:", r)
	case <-time.After(100 * time.Millisecond):
		fmt.Println("Căutarea pentru frigider a durat prea mult")
	}
}

Rezultat

Găsit: laptop: 3 bucăți în stoc
Căutarea pentru frigider a durat prea mult

Exemplul 2: Valoarea primită

Pe canal sosește momentul expirării, care diferă la fiecare rulare.

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println("Aștept 1 secundă...")
	t := <-time.After(time.Second)
	fmt.Println("Gata la", t.Format("15:04:05.000"))
}

Rezultat posibil (diferă la fiecare rulare)

Aștept 1 secundă...
Gata la 11:42:08.004

Greșeli frecvente

  • Creezi canalul rezultatului fără buffer. Dacă expiră timpul, goroutine-ul rămâne blocat pentru totdeauna la scriere. Folosește make(chan T, 1).
  • Pui time.After într-un select din buclă crezând că limitează toată bucla: fiecare trecere creează un temporizator nou. Creează-l o dată, înainte de buclă.

Comenzi înrudite

  • time.Timer: Un temporizator care trimite un singur semnal pe canalul C după o durată; poate fi oprit (Stop) sau repornit (Reset).
  • time.Tick: Returnează un canal care primește o valoare la fiecare interval d, la nesfârșit; bun pentru sarcini repetate.
  • time.Sleep: Oprește goroutine-ul curent pentru durata dată (de exemplu 500*time.Millisecond), apoi continuă.
  • context.WithTimeout: Creează un context care se anulează singur după durata dată; limita de timp standard pentru cereri și interogări.