context paketi, zaman yönetimi (iptal, zamanaşımı) ve kod parçaları arasında meta veri iletimi için standarttır, özellikle goroutine ve dış çağrılar (HTTP, DB) ile çalışırken.
Oluşturma:
Context'i sonlandırmak, kaynakların doğru bir şekilde serbest bırakılması için önemlidir. Örnek:
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() // devamında ctx goroutine/HTTP isteğinde kullanılır
Tipik desen — context'i fonksiyonların ilk argümanı olarak iletmek, örnek:
func process(ctx context.Context) error { ... }
Gerçek bir context yerine context.TODO() ve context.Background() ne zaman geçirilebilir ve aralarındaki fark nedir?
Birçok kişi context.Background()'ı yer tutucu olarak kullanıyor. Ama:
context.Background() — ağaçtaki kök, sadece main() ve testlerde, "context ağacının" başlatılmasında kullanılmalıdır.context.TODO() kullanımları belirsiz olduğunda, geçici bir çözüm olarak kullanılır - yeniden yapılandırma sırasında geçici "delikleri kapatmak" için. Production kodunda TODO kabul edilemez: neyin ve nereye iletileceğini kesin olarak bilmek gerekir.Hikaye
Mikroserviste context.WithTimeout() oluşturduktan sonra cancel() çağrılmayı unuttular — istekler takıldı, tamamlanan goroutine'ler çalıştırma zamanında "açık" zamanlayıcılar bırakıyor, bu da bellek sızıntısına yol açıyordu.
Hikaye
Handler'larda gelen isteğe ait context yerine context.Background() geçildiği için iptal zinciri ve trace-id kayboldu, bu nedenle zamanaşımı kısıtlamaları çalışmadı, istek iptalleri gerçekleşmedi.
Hikaye
context.WithValue() üzerinden geliştiriciler veri geçiyordu, ama anahtarlar string olduğu için. Sonuç olarak, farklı paketlerden gelen anahtarların çakışma olasılığı nedeniyle beklenmedik hatalar oluşuyordu ("anahtar zaten meşgul"). Doğru uygulama: anahtarlar için benzersiz tipler kullanmaktır.