http.Handler Arayüzü
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 77 / 107.
http.Handler arayüzü, Go'nun web sunucusu mimarisinin temelidir. HTTP isteklerinin nasıl işlendiğini tanımlar ve bunu uygulayan herhangi bir tür web isteklerine hizmet verebilir.
Arayüz oldukça basittir:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}ServeHTTP metoduna sahip herhangi bir tür, HTTP isteklerini işleyebilir. İşte özel bir işleyici:
type GreetHandler struct {
Greeting string
}
func (h GreetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s, visitor!", h.Greeting)
}Bu işleyiciyi doğrudan bir sunucuyla kullanabilirsiniz:
handler := GreetHandler{Greeting: "Welcome"}
http.Handle("/greet", handler)Daha basit durumlar için Go, normal bir fonksiyonu bir işleyiciye (handler) dönüştürmenize olanak tanıyan bir tür olan http.HandlerFunc sağlar:
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
}
http.Handle("/hello", http.HandlerFunc(hello))İşleyicilerin (handlers) diğer işleyicileri sarmalayabildiğini fark ettiğinizde bu arayüzün gücü netleşir. Bu, orijinal işleyici mantığını değiştirmeden günlükleme (logging), kimlik doğrulama (authentication) veya diğer çapraz kesen ilgileri (cross-cutting concerns) eklediğiniz ara yazılım (middleware) desenlerini mümkün kılar.
Görev
KolayWeb isteklerinin nasıl işlendiğini simüle eden basit bir HTTP işleyici (handler) sistemi kuralım! Bu ortamda gerçek bir HTTP sunucusu çalıştıramadığımız için, http.Handler arayüzünü (interface) uygulayan işleyiciler oluşturacak ve sahte (mock) istek/yanıt nesneleriyle çalışarak bunların istekleri nasıl işlediğini göstereceksiniz.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
handlers.go: Özel HTTP işleyicilerinizi tanımlayın.Bir HTTP yanıtına ne yazılacağını yakalayan bir
MockResponseWriteryapısı (struct) oluşturun. Yanıt gövdesini bir dize (string) olarak saklamalı ve gövdeye veri ekleyen birWrite(data []byte) (int, error)yöntemi uygulamalıdır. Biriken yanıtı almak için birBody() stringyöntemi ekleyin.Bir HTTP isteğini simüle etmek için
PathveMethoddize alanlarına sahip birMockRequestyapısı oluşturun.Şimdi
http.Handlerarayüz desenini uygulayan (bir*MockResponseWriterve*MockRequestalan birServeHTTPyöntemine sahip) iki işleyici yapısı oluşturun:Messagealanına sahipWelcomeHandler- mesajı ve ardından istek yolunu yazarMethodHandler- istek yöntemine göre farklı yanıtlar yazar: GET için"Fetching data", POST için"Creating resource"ve diğer her şey için"Method not supported"
main.go: İstekleri işleyicileriniz aracılığıyla işleyin.Bir işleyici türü (
welcomeveyamethod) okuyun, ardından istek ayrıntılarını okuyun. Welcome işleyicisi için karşılama mesajını da okuyun.Uygun işleyiciyi oluşturun, sahte bir istek oluşturun ve işlemek için
ServeHTTPyöntemini çağırın. Yanıt gövdesini yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: İşleyici türü (
welcomeveyamethod) - Satır 2: İstek yolu (path)
- Satır 3: İstek yöntemi (method)
- Satır 4 (yalnızca welcome için): Karşılama mesajı
Örneğin, şu girdi verildiğinde:
welcome
/home
GET
Hello fromÇıktınız şu olmalıdır:
Hello from /homeVe şu girdi verildiğinde:
method
/api/users
POSTÇıktınız şu olmalıdır:
Creating resourceVe şu girdi verildiğinde:
method
/api/data
GETÇıktınız şu olmalıdır:
Fetching dataVe şu girdi verildiğinde:
method
/api/items
DELETEÇıktınız şu olmalıdır:
Method not supportedBu zorluk, http.Handler arayüzünün temel kavramını gösterir; ServeHTTP yöntemine sahip herhangi bir tür istekleri işleyebilir. Gerçek uygulamalarda, http.ResponseWriter ve *http.Request Go'nun standart kütüphanesinden gelir, ancak işleyicileri uygulama deseni tamamen aynı kalır.
Kopya kağıdı
http.Handler arayüzü, Go'nun web sunucusu mimarisinin temelidir:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}ServeHTTP metoduna sahip herhangi bir tür, HTTP isteklerini işleyebilir:
type GreetHandler struct {
Greeting string
}
func (h GreetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s, visitor!", h.Greeting)
}Sunucuya bir işleyici (handler) kaydedin:
handler := GreetHandler{Greeting: "Welcome"}
http.Handle("/greet", handler)Daha basit durumlar için, bir fonksiyonu işleyiciye dönüştürmek üzere http.HandlerFunc kullanın:
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
}
http.Handle("/hello", http.HandlerFunc(hello))İşleyiciler diğer işleyicileri sarmalayabilir; bu da günlükleme (logging), kimlik doğrulama (authentication) veya diğer çapraz kesen ilgiler (cross-cutting concerns) için ara yazılım (middleware) desenlerini mümkün kılar.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// İşleyici türünü oku
scanner.Scan()
handlerType := scanner.Text()
// İstek yolunu oku
scanner.Scan()
path := scanner.Text()
// İstek yöntemini oku
scanner.Scan()
method := scanner.Text()
// Sahte istek oluştur
request := &MockRequest{
Path: path,
Method: method,
}
// Sahte yanıt yazıcısı oluştur
response := &MockResponseWriter{}
// TODO: handlerType'a bağlı olarak uygun işleyiciyi oluşturun
// Eğer handlerType "welcome" ise, karşılama mesajını okuyun ve WelcomeHandler oluşturun
// Eğer handlerType "method" ise, MethodHandler oluşturun
// İşleyici üzerinde response ve request ile ServeHTTP'yi çağırın
if handlerType == "welcome" {
scanner.Scan()
message := scanner.Text()
// TODO: Mesaj ile WelcomeHandler oluşturun ve ServeHTTP'yi çağırın
_ = message // Uygularken bu satırı kaldırın
} else if handlerType == "method" {
// TODO: MethodHandler oluşturun ve ServeHTTP'yi çağırın
}
// Yanıt gövdesini yazdır
fmt.Println(response.Body())
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1Go OOP Temelleri
Harici DosyalarGo Çalışma Alanı ve ModüllerPaketler ve İçe AktarmalarDışa Aktarılan ve Aktarılmayan İsimlerGo'da OOP'ye GirişSınıf Olarak Struct'larStruct'larda Metot TanımlamaPointer ve Değer AlıcılarStruct BaşlatmaYapıcı FonksiyonlarÖzet - Basit Hesap Makinesi4Arayüzler
Arayüzlere GirişÖrtük UygulamaSözleşme Olarak ArayüzBoş Arayüz (any)Tür OnaylamaTür SeçimiArayüz BileşimiStringer ve Error ArayüzleriÖzet - Şekil Hesaplayıcı7Kapsülleme
Dışa Aktarılan ve Aktarılmayan AlanlarPaket Seviyesinde KapsüllemeGetter ve Setter MetotlarıGo'da Bilgi GizlemeÖzet - Öğrenci Kayıtları10Generics (Go 1.18+)
Generics'e GirişTür ParametreleriTür KısıtlamalarıGeneric Struct'larGeneric Metotlar İçin Geçici ÇözümÖzet - Generic Koleksiyon13Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıAbstract Factory KalıbıObserver KalıbıStrategy Kalıbı2Türler ve Struct'lar: Derinlemesine İnceleme
Temel ve Bileşik TürlerÖzel Tür TanımlamalarıStruct EtiketleriAnonim Struct'larİç İçe Geçmiş Struct'larSıfır Değerler ve VarsayılanlarÖzet - Rehber5Kalıtım Yerine Kompozisyon
Go'da Neden Kalıtım YokStruct Gömme TemelleriMetot YükseltmeBirden Fazla Struct GömmeGömme vs AgregasyonGömülü Metotları GölgelemeÖzet - Çalışan Hiyerarşisi8Hata Yönetimi ve OOP
error ArayüzüÖzel Hata TürleriHata Sarmalama (fmt.Errorf)Sentinel Hatalarerrors.Is() ve errors.As()Panic, Defer ve RecoverÖzet - Dosya Ayrıştırıcı11Standart Kütüphane ve OOP
io.Reader ve io.Writersort.Interface Arayüzüfmt.Stringer ArayüzüStruct'lar ile encoding/jsonhttp.Handler ArayüzüÖzet - REST API Modelleri3İşaretçiler ve Bellek
Go'da İşaretçi TemelleriStruct İşaretçileriDeğer ile Geçme ve Referans ile Geçmenew() FonksiyonuGo'da Garbage CollectionÖzet - Linked List Oluşturucu6Go'da Polimorfizm
Interface'ler ile PolimorfizmGo'da Duck TypingInterface Karşılama KurallarıPolimorfik KoleksiyonlarDependency InjectionÖzet - Payment Processor9Eşzamanlılık ve OOP
Goroutine TemelleriKanallar ve İletişimTamponlu ve Tamponsuz KanallarSelect İfadesisync.Mutex ve sync.RWMutexsync.WaitGroupThread-Safe Struct TasarımıÖzet - Worker Pool