Goroutine Temelleri
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 59 / 107.
Bir goroutine, Go çalışma zamanı (runtime) tarafından yönetilen hafif bir yürütme iş parçacığıdır. Önemli miktarda bellek tüketen geleneksel iş parçacıklarının aksine, goroutine'ler sadece birkaç kilobaytlık yığın (stack) alanı ile başlar ve bu da binlercesini eşzamanlı olarak çalıştırmanıza olanak tanır.
Bir goroutine başlatmak için, bir fonksiyon çağrısından önce go anahtar kelimesini yerleştirmeniz yeterlidir:
func sayHello(name string) {
fmt.Println("Hello,", name)
}
func main() {
go sayHello("Alice") // eşzamanlı olarak çalışır
go sayHello("Bob") // eşzamanlı olarak çalışır
time.Sleep(100 * time.Millisecond)
fmt.Println("Done")
}go sayHello("Alice") yürütüldüğünde, sayHello fonksiyonunun bitmesini beklemez. Bunun yerine, sayHello arka planda çalışırken hemen bir sonraki satıra geçer. Bu yüzden time.Sleep fonksiyonuna ihtiyaç duyarız—o olmadan, goroutine'ler tamamlanmadan önce main sonlanır.
Goroutine'leri anonim fonksiyonlarla da başlatabilirsiniz:
go func(msg string) {
fmt.Println(msg)
}("Hello from goroutine")main fonksiyonunun kendisi bir goroutine içinde çalışır. Bu fonksiyon sonlandığında, diğer tüm goroutine'ler anında durdurulur; tamamlanma şansı bulamazlar. time.Sleep kullanmak geçici bir çözümdür; gelecek derslerde kanallar (channels) ve bekleme grupları (wait groups) ile doğru senkronizasyon tekniklerini öğreneceksiniz.
Görev
KolayGoroutine'leri kullanarak birden fazla görevi eşzamanlı olarak yürüten bir görev çalıştırıcı (task runner) oluşturalım. Görevlerin arka planda çalıştığı ve ana programın devam ettiği basit bir sistem oluşturarak, goroutine'lerin eşzamanlı yürütmeyi nasıl sağladığını göreceksiniz.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
tasks.go: Görev yürütme mantığınızı tanımlayın.Name(string) veDuration(int, milisaniye cinsinden) alanlarına sahip birTaskyapısı (struct) oluşturun.Tasküzerinde, görevin süresi kadar uyuyarak çalışmayı simüle eden ve ardından şunu yazdıran birRun()metodu uygulayın:Task [Name] completedHer bir görevin
Run()metodunu bir goroutine olarak başlatan birRunAllTasks(tasks []Task)fonksiyonu oluşturun. Tüm goroutine'leri başlattıktan sonra, tamamlanmalarına izin vermek için 500 milisaniye uyumalı ve ardından şunu yazdırmalıdır:All tasks launchedmain.go: Görev bilgilerini okuyun ve eşzamanlı yürütmeyi koordine edin.Görev sayısını okuyun, ardından her görevin adını ve süresini okuyun. Görevleri oluşturun ve bunları
RunAllTasksfonksiyonuna iletin. Fonksiyon döndükten sonra şunu yazdırın:Main function done
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Görev sayısı (tam sayı)
- Sonraki satırlar: Her görev için iki satır - görev adı ve ardından milisaniye cinsinden süresi
Örneğin, şu girdi verildiğinde:
3
Download
100
Process
50
Upload
75Çıktınız, tamamlanan görevleri (eşzamanlılık nedeniyle sıra değişebilir) ve ardından tamamlanma mesajlarını göstermelidir:
Task Process completed
Task Upload completed
Task Download completed
All tasks launched
Main function doneNot: Goroutine'ler eşzamanlı çalıştığı için, süresi daha kısa olan görevler genellikle daha önce biter. Görevlerin tamamlanma sırası sürelerine bağlıdır - kısa süreli görevler uzun süreli olanlardan önce tamamlanır.
Gecikmeler için time.Duration ve time.Millisecond ile birlikte time.Sleep kullanın. RunAllTasks içindeki uyutma işlemi olmazsa, fonksiyonun goroutine'ler işlerini bitirmeden döneceğini unutmayın.
Kopya kağıdı
Bir goroutine, Go çalışma zamanı (runtime) tarafından yönetilen hafif bir yürütme iş parçacığıdır (thread). Goroutine'ler sadece birkaç kilobaytlık yığın (stack) alanı ile başlar ve binlercesini eşzamanlı olarak çalıştırmanıza olanak tanır.
Bir goroutine başlatmak için, bir fonksiyon çağrısından önce go anahtar kelimesini yerleştirin:
func sayHello(name string) {
fmt.Println("Hello,", name)
}
func main() {
go sayHello("Alice") // eşzamanlı olarak çalışır
go sayHello("Bob") // eşzamanlı olarak çalışır
time.Sleep(100 * time.Millisecond)
fmt.Println("Done")
}go sayHello("Alice") yürütüldüğünde, sayHello fonksiyonunun bitmesini beklemez. Bunun yerine, sayHello arka planda çalışırken hemen bir sonraki satıra geçer.
Goroutine'leri anonim fonksiyonlarla başlatabilirsiniz:
go func(msg string) {
fmt.Println(msg)
}("Hello from goroutine")main fonksiyonunun kendisi de bir goroutine içinde çalışır. O döndüğünde, diğer tüm goroutine'ler derhal sonlandırılır. main fonksiyonu çıkmadan önce goroutine'lerin tamamlanmasına izin vermek için time.Sleep kullanın.
Kendin dene
package main
import (
"fmt"
)
func main() {
// Görev sayısını oku
var numTasks int
fmt.Scanln(&numTasks)
// TODO: Görevleri tutmak için bir slice oluşturun
// TODO: Her bir görevin adını ve süresini okuyun
// Her görev için:
// - Görev adını oku
// - Süreyi oku (tam sayı olarak)
// - Bir Task oluşturun ve slice'ınıza ekleyin
// TODO: Görev slice'ınız ile RunAllTasks fonksiyonunu çağırın
// TODO: "Main function done" yazdırın
}
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 Pool