Go'nun standart kütüphanesiyle ne kadar uzağa gidilir
Go'nun zengin standart kütüphanesinin gerçekte ne kadar yol kat ettirdiğini, harici bağımlılık ekleme kararını somut örneklerle tartıyorum.
Go öğrenmeye başlayanların erken fark ettiği şeylerden biri: dilin standart kütüphanesi (standard library) alışılmadık derecede zengin. HTTP sunucusu, JSON işleme, şifreleme, dosya sistemi, şablon motoru, test altyapısı — bunların hepsi üçüncü parti paket olmadan kullanılabiliyor.
PHP dünyasından gelince bu bir kültür şoku. PHP’de üçüncü parti paket kurmadan neredeyse hiçbir şeyi “modern” biçimde yapamıyorsunuz. Composer olmadan çalışmak teorik olarak mümkün ama pratik olarak tercih edilmiyor. Go’da ise standart kütüphane gerçekten kendi başına bir üretim tercihi.
Standart kütüphane neyi kapsıyor
Go’da import ifadesinin ardında github.com görmeden yapabileceklerinize kısaca bakalım:
HTTP servisi: net/http paketi hem client hem server tarafı sağlıyor. Basit bir servis için router kütüphanesi gerekmez:
package main
import (
"encoding/json"
"net/http"
)
type Response struct {
Message string `json:"message"`
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(Response{Message: "ok"})
}
func main() {
http.HandleFunc("/health", healthHandler)
http.ListenAndServe(":8080", nil)
}
Bu kod, bir üretim servisinin sağlık kontrol ucu için yeterli. Ek bağımlılık yok.
JSON işleme: encoding/json ile hem serialization hem deserialization mümkün. Büyük veri setlerinde ya da özel dönüşüm senaryolarında başka paketlere bakıyorum, ama standart kullanım durumları için encoding/json yeterli.
Veritabanı erişimi: database/sql arayüzünü driver’lar gerçekleştiriyor. Sürücü paketini dışarıdan alıyorsunuz, ama ORM zorunluluğu yok. Saf SQL’i standart kütüphane üzerinden çalıştırmak doğal.
Şablon motoru: html/template paketi XSS (Cross-Site Scripting) korumasını yerleşik olarak sunuyor. Sunucu taraflı HTML üretimi için başka bir şeye ihtiyaç yok.
Test altyapısı: testing paketi table-driven tests, benchmark ve fuzz test desteğiyle geliyor. Go’nun test kültürü büyük ölçüde bu paketin üzerine kurulu.
Nerede sınıra geliyorsunuz
Standart kütüphane her şeyi karşılamıyor ve bu bilinçli bir tasarım kararı. En çok sınıra geldiğim yerler:
Routing. net/http’nin varsayılan router’ı path parametrelerini (:id gibi) desteklemiyor. Go 1.22 ile bu kısıtlama kısmen giderildi — pattern sözdizimi eklendi:
// Go 1.22+
http.HandleFunc("GET /users/{id}", getUserHandler)
Ama karmaşık yönlendirme senaryolarında, özellikle middleware zinciri ve grup yapılandırması gerektiğinde chi ya da gorilla/mux gibi paketlere başvuruyorum.
ORM. database/sql ile saf SQL yazmak bir süre sonra tekrarlı oluyor. sqlx gibi hafif bir kütüphane standart arayüzü korurken struct taramasını kolaylaştırıyor. Ağır bir ORM almadan yapabildiğim durumlar çok daha fazla.
Doğrulama. Standart kütüphanede doğrulama kütüphanesi yok. go-playground/validator bu ihtiyacın fiili standardı haline geldi.
Loglama. log/slog paketi Go 1.21’de geldi ve structured loglama için artık standart kütüphane yeterli. Önceki sürümlerde zap ya da zerolog zorunluydu.
Az bağımlılığın değeri
Go topluluğunun “vendor her şeyi kontrol edin” yaklaşımı ve minimal bağımlılık kültürü birbiriyle bağlantılı. Daha az bağımlılık şu anlama geliyor: derleme süresi daha kısa, güvenlik açığı yüzeyi daha küçük, bağımlılık güncelleme yükü daha az.
Bir paketi eklemeden önce şu soruyu soruyorum: bu paketi standart kütüphaneyle ya da birkaç yardımcı fonksiyonla karşılayabilir miyim? Çoğu zaman cevap evet. Yanıt hayır olduğunda paket ekliyorum, ama bu bir karar — varsayılan değil.
PHP’de Composer olmadan yazmayı düşünmüyorum; ekosistem o şekilde kurulu. Go’da ise standart kütüphane bir başlangıç noktası değil, uzun süre yeterli olan gerçek bir seçenek. Bu fark, bağımlılıklara bakış açımı da biçimlendirdi.