Kanallar ve İletişim
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 60 / 107.
Channels, Go'da goroutineler arasındaki iletişim için kullanılan temel mekanizmadır. Goroutineler belleği doğrudan paylaşmak yerine, Go'nun şu felsefesini izleyerek kanallar aracılığıyla değer gönderip alır: "Belleği paylaşarak iletişim kurma; iletişim kurarak belleği paylaş."
chan anahtar sözcüğüyle make işlevini kullanarak bir kanal oluşturun:
messages := make(chan string)Değerleri göndermek ve almak için ok operatörünü <- kullanın. Ok, veri akışının yönünü gösterir:
func main() {
messages := make(chan string)
go func() {
messages <- "hello" // kanala gönder
}()
msg := <-messages // kanaldan al
fmt.Println(msg) // Çıktı: hello
}Varsayılan olarak, diğer taraf hazır olana kadar gönderme ve alma işlemleri bloklanır. Goroutine "hello" gönderdiğinde, main almaya hazır olana kadar bekler. Bu bloklama davranışı yerleşik senkronizasyon sağlar: time.Sleep gerekmez.
Daha fazla değer gönderilmeyeceğini belirtmek için bir kanalı kapatabilirsiniz. Alıcılar bunu algılayabilir:
close(messages)
msg, ok := <-messages
if !ok {
fmt.Println("Channel closed")
}Kanallar türlere sahiptir: bir chan string yalnızca dizeler taşıyabilir. Bu tür güvenliği, goroutine'lerin doğru veri türleriyle iletişim kurmasını sağlar ve hataları çalışma zamanı yerine derleme zamanında yakalar.
Görev
Kolaygoroutine'ların channel'lar aracılığıyla nasıl iletişim kurduğunu gösteren bir message relay sistemi oluşturalım. message'ların farklı işleme aşamaları arasında aktığı ve her aşamanın eşzamanlı olarak çalıştığı bir pipeline oluşturacaksın.
kodunu iki dosya arasında düzenleyeceksin:
relay.go: message işleme pipeline'ını tanımla.ID(int) veContent(string) fields'larına sahip birMessagestruct'ı oluştur.Pipeline'ının farklı aşamalarını temsil eden üç function uygula:
Producer(messages []Message, out chan Message)- Bir message dilimi alır ve her birini output channel'ına gönderir. Tüm message'ları gönderdikten sonra tamamlanmayı bildirmek için channel'ı kapat.Transformer(in chan Message, out chan Message)- Input channel'ından message'ları alır, her message'ın content'ini büyük harfe dönüştürür ve dönüştürülen message'ı output channel'ına gönderir. Input channel kapatıldığında (iki değerli alma biçimi kullanılarak algılanır) output channel'ını kapat.Consumer(in chan Message) []string- Input channel'ından tüm message'ları alır ve bunları biçimlendirilmiş string'lerden oluşan bir dilimde collect eder. Her string şu formatı izlemelidir:Message [ID]: [Content]. Channel kapatıldığında dilimi döndür.
main.go: Pipeline'ı kur ve eşzamanlı message akışını yönet.message sayısını oku, ardından her message'ın ID'sini ve content'ini oku. Message'ları oluştur ve üç pipeline aşamanı birbirine bağlamak için iki channel kur. Producer ve Transformer'ı goroutine olarak başlat, ardından sonuçları collect etmek için Consumer'ı main goroutine'inde çalıştır. Her sonucu ayrı bir line'a yazdır.
Aşağıdaki input'lar sağlanacaktır:
- Line 1: Message sayısı (integer)
- Sonraki line'lar: Her message için iki line - message ID'si (integer), ardından content'i (string)
Örneğin, şu verilirse:
2
1
hello world
2
go channelsOutput'un şu şekilde olmalıdır:
Message 1: HELLO WORLD
Message 2: GO CHANNELSPipeline şu şekilde akar: Producer message'ları gönderir → Transformer büyük harfe converts eder → Consumer sonuçları collect eder ve biçimlendirir. Her ok, eşzamanlı aşamaları birbirine bağlayan bir channel'ı temsil eder. Büyük harfe dönüştürme için strings package'ını kullan.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Mesaj sayısını oku
nLine, _ := reader.ReadString('\n')
n, _ := strconv.Atoi(strings.TrimSpace(nLine))
// Mesajları oku
messages := make([]Message, n)
for i := 0; i < n; i++ {
idLine, _ := reader.ReadString('\n')
id, _ := strconv.Atoi(strings.TrimSpace(idLine))
contentLine, _ := reader.ReadString('\n')
content := strings.TrimSpace(contentLine)
messages[i] = Message{ID: id, Content: content}
}
// TODO: Pipeline aşamalarını bağlamak için iki kanal oluştur
// TODO: Producer'ı bir goroutine olarak başlat
// TODO: Transformer'ı bir goroutine olarak başlat
// TODO: Consumer'ı ana goroutine'de çalıştır ve sonuçları topla
// TODO: Her sonucu ayrı bir satıra yazdır
}
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