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:
- https://github.com/go-chi/chi
- https://github.com/valyala/fasthttp
- https://github.com/labstack/echo
- https://github.com/gofiber/fiber
- https://github.com/gin-gonic/gin
- https://github.com/go-kratos/kratos (microservice)
- https://github.com/go-kit/kit (microservice)
godoc
’ta:
- https://pkg.go.dev/net/http@go1.21.0 (http)
- https://pkg.go.dev/net/http@go1.21.0#hdr-Servers (server)
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.
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:
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.