Înainte de Go 1.21, pentru a executa o acțiune atunci când un context era anulat (de exemplu, forțarea închiderii unei conexiuni de rețea sau întreruperea unui proces extern), programatorii erau forțați să pornească o goroutine dedicată care asculta pe canalul <-ctx.Done(). Această practică irosea resurse și introducea riscuri de scurgeri de goroutine-uri. Funcția context.AfterFunc din Go 1.21 programează o funcție de callback care va fi executată automat într-o goroutine nouă imediat ce contextul este anulat sau expiră.
Întreruperea unei conexiuni lente la timeout cu context.AfterFunc
package main
import (
"context"
"fmt"
"net"
"time"
)
func descarcaDateSecurizat(ctx context.Context, adresa string) error {
conn, err := net.Dial("tcp", adresa)
if err != nil {
return err
}
defer conn.Close()
// Programăm închiderea forțată a socket-ului dacă contextul este anulat:
stopCuratare := context.AfterFunc(ctx, func() {
fmt.Println("Context anulat! Se forțează închiderea conexiunii TCP...")
conn.Close()
})
// Dacă funcția se termină cu succes înainte de anulare, anulăm callback-ul:
defer stopCuratare()
// Operațiune de citire de lungă durată:
buffer := make([]byte, 1024)
_, err = conn.Read(buffer)
return err
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
_ = descarcaDateSecurizat(ctx, "example.com:80")
}