Menu
Coddy logo textTech

Select İfadesi

Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 62 / 107.

select ifadesi, bir goroutine'in aynı anda birden fazla kanal işlemi üzerinde beklemesini sağlar. Bir switch ifadesine benzer, ancak her bir case bir kanal gönderimi veya alımı içerir. Birden fazla kanal hazır olduğunda, select rastgele birini seçer.

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)
    
    go func() { ch1 <- "from channel 1" }()
    go func() { ch2 <- "from channel 2" }()
    
    select {
    case msg1 := <-ch1:
        fmt.Println(msg1)
    case msg2 := <-ch2:
        fmt.Println(msg2)
    }
}

select olmadan, ch1 kanalından veri almak veri gelene kadar bloklanır ve bu durum ch2 üzerindeki verinin potansiyel olarak kaçırılmasına neden olabilir. select ile, hangi kanal önce veri alırsa o işlenir.

default durumu select ifadesini bloklamayan (non-blocking) hale getirir; hiçbir kanal hazır değilse anında çalışır:

select {
case msg := <-messages:
    fmt.Println("Received:", msg)
default:
    fmt.Println("No message available")
}

Yaygın bir desen, select ifadesini, belirtilen süreden sonra bir değer alan bir kanal döndüren time.After kullanarak zaman aşımlarıyla birleştirir:

select {
case result := <-ch:
    fmt.Println("Got result:", result)
case <-time.After(2 * time.Second):
    fmt.Println("Timeout!")
}

Bu, bir kanal işleminin hiçbir zaman tamamlanmayabileceği durumlarda programınızın sonsuza kadar beklemesini engeller.

challenge icon

Görev

Kolay

Birden fazla eşzamanlı veri kaynağını işlemek için select ifadesini kullanan bir servis monitörü oluşturalım. Monitörünüz farklı servis kanallarını aynı anda dinleyecek ve veri geldiğinde veya hiçbir güncelleme olmadığında uygun şekilde yanıt verecektir.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • monitor.go: Select tabanlı kanal işleme ile servis izleme mantığınızı tanımlayın.

    Name (string) ve Status (string) alanlarına sahip bir ServiceUpdate yapısı (struct) oluşturun.

    Üç kanal alan bir Monitor fonksiyonu uygulayın: primary chan ServiceUpdate, backup chan ServiceUpdate ve done chan bool. Bu fonksiyon, her üç kanalı da aynı anda dinlemek için select kullanmalıdır:

    • primary kanalından veri alındığında: Primary: [Name] is [Status] şeklinde formatlanmış dizeyi döndürün.
    • backup kanalından veri alındığında: Backup: [Name] is [Status] şeklinde formatlanmış dizeyi döndürün.
    • done kanalından veri alındığında: Monitoring stopped döndürün.

    Tek bir updates chan ServiceUpdate alan ve bloklamayan (non-blocking) bir kontrol gerçekleştirmek için default durumuyla birlikte select kullanan bir CheckStatus fonksiyonu uygulayın:

    • Eğer bir güncelleme mevcutsa: Update available: [Name] döndürün.
    • Eğer güncelleme mevcut değilse (default durumu): No updates pending döndürün.
  • main.go: Kanalları kurun ve hem bloklayan hem de bloklamayan select davranışını gösterin.

    Hangi senaryonun çalıştırılacağını belirleyen bir modu girdiden okuyun: primary, backup, stop veya check.

    primary, backup ve stop modları için: ayrıca bir servis adı ve durumu okuyun. Üç kanalı oluşturun, moda bağlı olarak uygun kanala veri gönderen bir goroutine başlatın, ardından Monitor fonksiyonunu çağırın ve sonucunu yazdırın.

    check modu için: bir servis adı ve durumu, ayrıca kontrol etmeden önce veri gönderilip gönderilmeyeceğini belirten bir bayrak (send veya nosend) okuyun. 1 kapasiteli bir tamponlu (buffered) kanal oluşturun. Eğer bayrak send ise, CheckStatus fonksiyonunu çağırmadan önce kanala bir güncelleme gönderin. CheckStatus sonucunu yazdırın.

Aşağıdaki girdiler sağlanacaktır:

  • Satır 1: Mod (primary, backup, stop veya check)
  • Satır 2: Servis adı
  • Satır 3: Servis durumu
  • Satır 4 (sadece check modu için): send veya nosend

Örneğin, şu girdi verildiğinde:

primary
Database
healthy

Çıktınız şu olmalıdır:

Primary: Database is healthy

Ve şu girdi verildiğinde:

check
Cache
active
nosend

Çıktınız şu olmalıdır:

No updates pending

Kopya kağıdı

select ifadesi, bir goroutine'in aynı anda birden fazla kanal işlemi üzerinde beklemesine olanak tanır. Bir switch ifadesi gibi çalışır, ancak her durum (case) bir kanal gönderimi veya alımı içerir:

select {
case msg1 := <-ch1:
    fmt.Println(msg1)
case msg2 := <-ch2:
    fmt.Println(msg2)
}

Birden fazla kanal hazır olduğunda, select rastgele birini seçer. select olmadan, bir kanaldan veri almak bloklanmaya neden olur ve potansiyel olarak başka bir kanaldaki verilerin kaçırılmasına yol açardı.

default durumu select ifadesini bloklamayan (non-blocking) hale getirir; eğer hiçbir kanal hazır değilse anında çalışır:

select {
case msg := <-messages:
    fmt.Println("Received:", msg)
default:
    fmt.Println("No message available")
}

Yaygın bir desen, select ifadesini, belirtilen süre sonunda bir değer alan bir kanal döndüren time.After kullanarak zaman aşımlarıyla (timeouts) birleştirmektir:

select {
case result := <-ch:
    fmt.Println("Got result:", result)
case <-time.After(2 * time.Second):
    fmt.Println("Timeout!")
}

Bu, bir kanal işleminin asla tamamlanmama ihtimaline karşı programınızın sonsuza kadar beklemesini engeller.

Kendin dene

package main

import (
	"fmt"
)

func main() {
	var mode string
	fmt.Scanln(&mode)

	var serviceName string
	fmt.Scanln(&serviceName)

	var serviceStatus string
	fmt.Scanln(&serviceStatus)

	// TODO: Farklı modları işle: "primary", "backup", "stop", "check"
	
	// "primary", "backup", "stop" modları için:
	// - Üç kanal oluşturun: primary, backup, done
	// - Uygun kanala veri gönderen bir goroutine başlatın
	// - Monitor fonksiyonunu çağırın ve sonucu yazdırın
	
	// "check" modu için:
	// - Ek bayrağı okuyun ("send" veya "nosend")
	// - 1 kapasiteli bir tamponlu kanal oluşturun
	// - Eğer bayrak "send" ise, kanala bir güncelleme gönderin
	// - CheckStatus fonksiyonunu çağırın ve sonucu yazdırın
	
}
quiz iconKendini test et

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