Sözleşme Olarak Arayüz
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 27 / 107.
Arayüzleri sözleşmeler olarak düşünmek, daha iyi Go programları tasarlamanıza yardımcı olur. Bir işlev bir arayüz türünü kabul ettiğinde şunu söylemiş olur: "Bana hangi somut türü verdiğiniz umurumda değil, yeter ki bu sözleşmeyi yerine getirsin."
Sözleşme tabanlı bu düşünme biçimi, belirli türler yerine davranışa odaklanan işlevler yazmanı sağlar. Çeşitli kaynaklardan gelen verileri işlemesi gereken bir işlevi ele alalım:
type DataSource interface {
FetchData() string
}
func ProcessData(src DataSource) {
data := src.FetchData()
fmt.Println("Processing:", data)
}ProcessData işlevi, bir veritabanı bağlantısı, bir API istemcisi veya bir dosya okuyucusu alıp almadığını bilmez ve bunu önemsemez. Yalnızca girdinin FetchData() işlemini gerçekleştirebilmesini gerektirir. Bu sözleşmeye uyan her tür işe yarar.
type Database struct{ ConnectionString string }
func (d Database) FetchData() string { return "data from DB" }
type APIClient struct{ Endpoint string }
func (a APIClient) FetchData() string { return "data from API" }
func main() {
db := Database{ConnectionString: "localhost"}
api := APIClient{Endpoint: "https://api.example.com"}
ProcessData(db) // Çalışıyor!
ProcessData(api) // Bu da çalışıyor!
}Bu sözleşme yaklaşımı kodunuzu daha test edilebilir hâle de getirir. Test sırasında gerçek veritabanlarına veya ağ bağlantılarına ihtiyaç duymadan arayüzü karşılayan bir sahte tür oluşturabilirsiniz. Test edilen işlev, sözleşme yerine getirildiği için aradaki farkı bilmez.
Görev
KolayArayüzlerin sözleşme olarak nasıl davrandığını gösteren bir bildirim sistemi oluşturalım. Bildirim göndermenin ne anlama geldiğini tanımlayan bir Notifier arayüzü oluşturacak, ardından bu sözleşmeye uyan birden çok bildirim kanalını uygulayacaksın.
Kodunu iki dosyaya ayıracaksın:
notifiers.go: Tek birNotifieryöntemine sahip birNotify(message string) stringarayüzü tanımla. Ardından bu sözleşmeyi karşılayan üç farklı yapı oluştur:ConsoleNotifier, birPrefixalanıylaFileNotifier, birFilenamealanıylaWebhookNotifier, birURLalanıyla
Notifyyöntemini uygulamalıdır.main.go: BirBroadcastAlertdeğerleri dilimini ve bir mesaj dizesini kabul edenNotifieradlı bir işlev oluştur. Bu işlev, her bildirimci içinNotifyyöntemini çağırmalı ve sonuçları yazdırmalıdır. Yapılandırmayı girdiden oku, üç bildirimci türünün tümünü oluştur ve bir uyarıyı hepsi üzerinden yayınla.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Konsol öneki
- 2. satır: Dosya adı
- 3. satır: Webhook URL'si
- 4. satır: Uyarı mesajı
Notify yöntemlerin şu biçimlerde dizeler döndürmelidir:
- ConsoleNotifier:
[Prefix] [message] - FileNotifier:
Writing to [Filename]: [message] - WebhookNotifier:
POST [URL]: [message]
Örneğin ALERT:, log.txt, https://hooks.example.com ve Server down! verildiğinde çıktın şu şekilde olmalıdır:
ALERT: Server down!
Writing to log.txt: Server down!
POST https://hooks.example.com: Server down!Bu tasarımın gücü, BroadcastAlert işlevinin belirli bildirimci türlerini bilmemesi veya önemsememesidir. Yalnızca her birinin Notifier sözleşmesini yerine getirmesini gerektirir. Daha sonra yayın işlevini hiç değiştirmeden bir SlackNotifier veya EmailNotifier ekleyebilirsin.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
)
// BroadcastAlert tüm notifiers aracılığıyla bir mesaj gönderir
// TODO: Bu fonksiyonu şunları yapacak şekilde uygula:
// - Notifier değerlerinden bir dilim ve bir mesaj dizesi kabul et
// - Her notifier üzerinde Notify çağır ve sonuçları yazdır
func BroadcastAlert(notifiers []Notifier, message string) {
// TODO: notifiers üzerinde döngü yap ve her bildirim sonucunu yazdır
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Konsol önekini oku
scanner.Scan()
prefix := scanner.Text()
// Dosya adını oku
scanner.Scan()
filename := scanner.Text()
// Webhook URL'sini oku
scanner.Scan()
url := scanner.Text()
// Uyarı mesajını oku
scanner.Scan()
message := scanner.Text()
// TODO: Üç notifier türünün tümünün örneklerini oluştur
// - prefix ile ConsoleNotifier
// - filename ile FileNotifier
// - URL ile WebhookNotifier
// TODO: Üç notifier'ın hepsini içeren bir Notifier dilimi oluştur
// TODO: BroadcastAlert'i notifiers ve message ile çağır
_ = prefix
_ = filename
_ = url
_ = message
fmt.Println("TODO: Implement the solution")
}
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ı3İş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 PoolKendi başına pratik yap: Online Go derleyicisi