ProgramlamaBackend Go geliştirici

Go'da yerleşik context paketi nasıl çalışır? Ne için kullanılır, context'leri nasıl doğru bir şekilde oluşturup sonlandırırız? Kullanımında hangi hatalar yapılır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

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.Background() — kök context
  • context.WithCancel(parent) — iptal ile yeni bir context
  • context.WithTimeout(parent, duration) — zamanaşımı ile
  • context.WithValue(parent, key, value) — veri ile

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 { ... }

Kandırıcı Soru

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.

Gerçek Hatalardan Örnekler


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.