İçeriğe geç
Muhammet Şafak
Diller 3 dk okuma

Go'da HTTP servisi yazmak: standart kütüphane yeter mi

Go'nun net/http paketiyle küçük bir HTTP servisi kurarken neyin geldiğini, neyin gelmediğini ve framework eşiğini tartışıyorum.


Go öğrenirken kendime verdiğim kurallardan biri şuydu: bir şeyi standart kütüphane ile kurmayı denemedikçe dışarıdan kütüphane eklemeyeceğim. Bu kural bazen can sıktı, çoğu zaman öğretti. HTTP servisi bu kuralı gerçekten test eden alan oldu.

PHP’de her şeyin üstünde bir framework çalışıyor; Laravel, Slim, ne olursa. Ham PHP ile HTTP sunucusu yazmak teorik olarak mümkün ama kimse yapmıyor. Go’da ise net/http paketi gerçekten kullanılabilir, production’da çalışan servisler standart kütüphaneyle yazılıyor. Bu fark zihniyet değişikliğine zorluyor.

net/http ile temel sunucu

Bir Go HTTP sunucusunu çalıştırmak birkaç satır:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        fmt.Fprintln(w, `{"status":"ok"}`)
    })

    http.ListenAndServe(":8080", nil)
}

Çalıştırıyor, port 8080’de yanıt veriyor. Bağımlılık sıfır. Bu basitlik ilk başta tatmin edici; ama bir API yazmaya başladığınızda sınırlar ortaya çıkıyor.

Standart kütüphanenin eksikleri

net/http’nin HandleFunc ile kayıt mekanizması yeterince esnek değil. Route parametresi — /users/123 gibi dinamik segmentler — standart kütüphanede yok. Her yolu elle parse etmeniz gerekiyor:

http.HandleFunc("/users/", func(w http.ResponseWriter, r *http.Request) {
    // "/users/" sonrasını elle çekiyoruz
    id := r.URL.Path[len("/users/"):]
    if id == "" {
        // liste döndür
        return
    }
    // tekil kayıt döndür
})

Bu yaklaşım iki-üç rota için idare ediyor, on rota için çekilmez hale geliyor. HTTP metodu (GET/POST/PUT/DELETE) ayrımını da elle yapmak gerekiyor:

switch r.Method {
case http.MethodGet:
    // GET işle
case http.MethodPost:
    // POST işle
default:
    http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
}

Bu switch bloğunu her handler’a kopyalamak kodu hızla şişiriyor. Standart kütüphane bu ortak pattern’ı soyutlamıyor; bunu kendiniz yazmak ya da bir kütüphaneye devretmek gerekiyor.

Framework eşiği nerede?

Bir kütüphane almadan önce şu soruyu soruyorum: standart kütüphanenin sağlamadığı şey ne kadar jenerik bir ihtiyaç? Route parametresi ve HTTP metodu yönlendirmesi jenerik ve evrensel; her serviste gerekli.

Bu noktada üçüncü parti kütüphanelere bakıyorum. Go ekosisteminde gorilla/mux ve chi bu boşluğu dolduran hafif router’lar. Framework değiller; yalnızca net/http’nin üstüne route parametresi ve metot eşleştirme ekliyorlar, standart http.Handler interface’ine uyuyorlar.

import "github.com/go-chi/chi/v5"

r := chi.NewRouter()

r.Get("/users/{id}", func(w http.ResponseWriter, req *http.Request) {
    id := chi.URLParam(req, "id")
    // id ile işle
})

http.ListenAndServe(":8080", r)

Temel felsefe korunuyor: standart kütüphanenin interface’lerine uyan, başka kütüphanelerle çakışmayan bir eklenti. Laravel benzeri büyük bir bağımlılık yığını değil.

chi’nin beni ikna eden tarafı standart http.Handler interface’ine tam uyum. Bir kütüphane seçerken bu uyuma dikkat ediyorum; standart interface’i bozan bir router, ekosisteme uymayan middleware ya da yardımcılarla çalışmayı zorlaştırıyor. chi ile yazdığım handler’ı başka herhangi bir net/http uyumlu yapıyla kullanmak mümkün.

JSON yanıtları ve hata yönetimi

Standart kütüphanede JSON serialization için encoding/json paketi var ve iyi çalışıyor:

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

func writeJSON(w http.ResponseWriter, status int, data interface{}) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(status)
    json.NewEncoder(w).Encode(data)
}

Bu küçük helper fonksiyon tekrar yazmayı ortadan kaldırıyor; tüm handler’lar bunu kullanıyor.

PHP ile karşılaştırma

Go’da HTTP servisi yazmak PHP’de framework olmadan yazmaktan farklı: standart kütüphane gerçekten production’a hazır, bakımlı ve hızlı. Ancak Laravel’in sunduğu kimlik doğrulama, ORM, queue, e-posta gibi katmanlar Go’da yok — ve olması gerekmiyor. Go servisleri çoğunlukla daha dar bir sorumluluğu çok iyi yapıyor; geniş kapsam için başka diller devreye giriyor.


Sonuç olarak: Go’da standart kütüphane çok fazlasını karşılıyor, ama her şeyi değil. Route parametresi ve metot yönlendirmesi için hafif bir kütüphane makul bir ödünleşim. Tam framework’e geçmek çoğu durum için erken bir karar — ihtiyaç gerçekten büyüdüğünde alınabilir bir karar.

Etiketler: #Go
Paylaş:

İlgili Yazılar

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi