# 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.

- Yayın: 2020-06-07
- Güncelleme: 2026-09-07
- Kategori: Diller
- Etiketler: Go
- Okuma süresi: 3 dk okuma
- Kaynak: https://muhammetsafak.com/tr/blog/go-da-http-servisi-yazmak-standart-kutuphane-yeter-mi/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
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 — [Go öğrenmeye neden başladığımı anlattığım yazıdaki](/tr/blog/polyglota-ilk-adim-neden-go-ogrenmeye-basladim/) niyetin doğrudan sonucuydu: dili araçlarının arkasından değil, kendisinden tanımak. 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:

```go
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 — bu yazıyı yazdığım sırada standart kütüphanede yoktu. Her yolu elle parse etmek gerekiyordu:

```go
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:

```go
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.

Buraya bugünden bir not düşmek gerekiyor: bu eksik kapandı. [Go 1.22, `net/http`'nin `ServeMux`'ına gelişmiş desen eşleştirmesi ekledi](https://go.dev/doc/go1.22#enhanced_routing_patterns) — `/items/{id}` gibi joker segmentler artık standart kütüphanede tanınıyor ve segmentin değerine `Request.PathValue` ile ulaşılıyor; `"POST /items/create"` biçiminde kayıt yapıldığında handler yalnız o metotla çağrılıyor. Yani yukarıdaki elle parse ve `switch r.Method` kalıpları 2024'ten beri zorunlu değil. Yazının geri kalanındaki muhakeme — bir kütüphaneyi ne zaman almalı — duruyor; değişen, eşiğin yeri.

## 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.

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

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 — [kendi tanıtımında "net/http ile %100 uyumlu" ve "dış bağımlılık yok, yalnız Go standart kütüphanesi" diyor](https://github.com/go-chi/chi). 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`](https://pkg.go.dev/encoding/json) paketi var ve iyi çalışıyor:

```go
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.

---

### Kaynaklar

- [Go 1.22 Release Notes: Enhanced routing patterns](https://go.dev/doc/go1.22#enhanced_routing_patterns)
- [Go Packages: net/http](https://pkg.go.dev/net/http)
- [Go Packages: encoding/json](https://pkg.go.dev/encoding/json)
- [go-chi/chi](https://github.com/go-chi/chi)
