Ana içeriğe geç

Bölüm 18/01: In-Memory Key-Value Store

Basit bir rest-api geliştireceğiz. Küçük ve basit bir REDIS klonu. Klon ama çok primitif bir klon. Key/Value çiftlerini hafızada tutan, listeleme, ekleme, silme, okuma ve güncelleme yani CRUDL (Create, Read, Update, Delete, List) operasyonları yapabileceğimiz bir servis. Diğer bir amacımız da hiçbir ek paket kullanmadan, go ile gelen paketleri kullanarak bu servisi geliştirmek.

Nelere ihtiyacımız var;

  • HTTP Server
  • Storage (hafızada tutacağımız map)

HTTP Server

Go, standart kütüphanesine production grade yani canlı ortamda gönül rahatlığıyla kullanabileceğimiz http sunucuyla birlikte geliyor. Hatta sadece sunucu değil istemcisi de var (http client). Tüm bu özellikler net/http paketi içinde.

net/http bize neler sağlar?

  • Web uygulamaları yapabiliriz
  • Statik dosya sunucusu olarak kullanabiliriz
  • Routing
  • Cookie yönetimi yapabiliriz

Keza pek çok popüler web frameworkleri de altta bu paketi kullanır:

godoc’ta:

Bizim ilgilendiğimiz kısım Server type:

type Server struct {
    // Addr optionally specifies the TCP address for the server to listen on,
    // in the form "host:port". If empty, ":http" (port 80) is used.
    // The service names are defined in RFC 6335 and assigned by IANA.
    // See net.Dial for details of the address format.
    Addr string

    Handler Handler // handler to invoke, http.DefaultServeMux if nil

    // others
}

Handler field’ı, Handler tipinde; Peki nedir bu?

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

Evet, bu bir interface. Herhangi bir tipin (ResponseWriter, *Request) alan bir fonksiyonu olursa o artık bir HTTP handler oluyor.

HTTP Handler ne yapar? istemcinin sunucudan yaptığı istekleri yakalayan ve geriye cevap dönen (byte cinsinden) şeydir.

Soru: ServeHTTP neden *Request (pointer) alırken ResponseWriter’ı (value) olarak alıyor? ResponseWriter dokümanı.

Özetle; bizim şöyle bir tipimiz olsa;

type foo struct {}
func (foo)ServeHTTP(http.ResponseWriter, *http.Request){
}

artık foo bir HTTP Handler olarak kullanılabilir.

örnek

https://go.dev/play/p/8dMERh1XZvg

$ go run src/18/basic-http-server/main.go

sonra tarayıcıyı açıp;

tebrikler, artık bir web sunucunuz var!

Biz, servisimizi geliştirirken biraz daha gelişmiş özellikleri olan http.Server’ı kullanacağız. Bizim bir kısım endpoint’leri yakalamamız gerekiyor. Bunun için request multiplexer’a ihtiyacımız var.

Hemen godoc’tan bir örneğe bakalım:

örnek

https://go.dev/play/p/T38GlxCvEpL

$ go run src/18/basic-mux/main.go

sonra tarayıcıyı açıp:

http.Server kullandığımız zaman;

http.Server{
    Addr:         ":8000",
    Handler:      mux,
    ReadTimeout:  ServerReadTimeout,
    WriteTimeout: ServerWriteTimeout,
    IdleTimeout:  ServerIdleTimeout,
}

gibi ek parametrelerde kullanabiliyoruz.