Go’da Concurrency: Goroutines ve Channels
Go’nun en güçlü özelliklerinden biri concurrency (eşzamanlılık) desteğidir. Bu yazıda goroutines ve channels’ı inceleyeceğiz.
Goroutines Nedir?
Goroutines, Go’nin hafif iş parçacıklarıdır (threads). Binlerce hatta milyonlarca goroutine aynı anda çalışabilir.
package main
import (
"fmt"
"time"
)
func sayHello(name string) {
fmt.Printf("Merhaba %s!\n", name)
}
func main() {
// Normal fonksiyon çağrısı
sayHello("Ahmet")
// Goroutine olarak çalıştırma
go sayHello("Mehmet")
go sayHello("Ayşe")
// Ana goroutine'in bitmesini beklemek için
time.Sleep(time.Millisecond * 100)
}
Anonim Goroutines
go func() {
fmt.Println("Anonim goroutine")
}()
// Parametre ile
go func(msg string) {
fmt.Println(msg)
}("Merhaba")
Channels
Channels, goroutines arasında iletişim kurmak için kullanılır:
// Channel oluşturma
ch := make(chan int)
// Gönderme
go func() {
ch <- 42 // Değer gönder
}()
// Alma
value := <-ch // Değer al (bloke eder)
fmt.Println(value)
Buffered Channels
// 3 kapasiteli buffered channel
ch := make(chan string, 3)
ch <- "birinci"
ch <- "ikinci"
ch <- "üçüncü"
// Bloke olmaz, çünkü kapasite dolmadı
Channel Yönleri
// Sadece gönderme
func sender(ch chan<- int) {
ch <- 42
}
// Sadece alma
func receiver(ch <-chan int) {
value := <-ch
fmt.Println(value)
}
// İki yönlü
func bidirectional(ch chan int) {
ch <- 42
value := <-ch
}
Select ile Çoklu Channel
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(time.Millisecond * 100)
ch1 <- "birinci"
}()
go func() {
time.Sleep(time.Millisecond * 200)
ch2 <- "ikinci"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("Channel 1:", msg1)
case msg2 := <-ch2:
fmt.Println("Channel 2:", msg2)
}
}
WaitGroup ile Senkronizasyon
import "sync"
var wg sync.WaitGroup
func worker(id int) {
defer wg.Done()
fmt.Printf("Worker %d çalışıyor\n", id)
}
func main() {
for i := 1; i <= 5; i++ {
wg.Add(1)
go worker(i)
}
wg.Wait() // Tüm worker'ların bitmesini bekle
}
Best Practices
- Channel ownership: Sahipliği açık belirleyin
- Buffered channels: Duruma göre kullanın
- Error handling: Error’ları channel üzerinden gönderin
- Context: İptal işlemleri için context kullanın
Örnek: Worker Pool
func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
for job := range jobs {
fmt.Printf("Worker %d: iş %d\n", id, job)
results <- job * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Worker'ları başlat
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1)
go worker(i, jobs, results, &wg)
}
// İşleri gönder
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
// Sonuçları al
go func() {
wg.Wait()
close(results)
}()
for result := range results {
fmt.Println("Sonuç:", result)
}
}
Yorumlar (0)
Henüz yorum yapılmamış. İlk yorumu sen yap!
Yorum Yap