A.33. Channel - Select
Channel membuat manajemen goroutine menjadi sangat mudah di Go. Namun perlu di-ingat, fungsi utama channel adalah bukan untuk kontrol eksekusi goroutine, melainkan untuk sharing data atau komunikasi goroutine.
Pada chapter A.59. sync.WaitGroup akan dibahas secara komprehensif tentang cara yang lebih optimal untuk kontrol eksekusi goroutine.
Tergantung jenis kasusnya, ada kalanya kita butuh lebih dari satu channel untuk komunikasi data antar goroutine. Penerimaan data pada banyak goroutine penerapannya masih sama, yaitu dengan menambahkan karakter <-
pada statement. Selain itu, ada juga cara lain yaitu menggunakan keyword select
. Keyword ini mempermudah kontrol penerimaan data via satu atau lebih dari satu channel.
Cara penggunaan select
untuk kontrol channel sama seperti penggunaan switch
untuk seleksi kondisi.
A.33.1. Penerapan Keyword select
Program berikut merupakan contoh sederhana penerapan keyword select
. Di sini disiapkan 2 buah goroutine, satu untuk menghitung rata-rata dari data array numerik, dan satu lagi untuk pencarian nilai tertinggi. Hasil operasi di masing-masing goroutine dikirimkan ke fungsi main()
via channel (ada dua channel). Di fungsi main()
sendiri, data tersebut diterima dengan memanfaatkan keyword select
.
Ok, langsung saja kita praktek. Pertama, siapkan 2 fungsi yang sudah dibahas di atas. Fungsi pertama digunakan untuk mencari rata-rata, dan fungsi kedua untuk penentuan nilai tertinggi dari sebuah slice.
package main
import "fmt"
import "runtime"
func getAverage(numbers []int, ch chan float64) {
var sum = 0
for _, e := range numbers {
sum += e
}
ch <- float64(sum) / float64(len(numbers))
}
func getMax(numbers []int, ch chan int) {
var max = numbers[0]
for _, e := range numbers {
if max < e {
max = e
}
}
ch <- max
}
Kedua fungsi tersebut dijalankan sebagai goroutine. Di akhir blok masing-masing fungsi, hasil kalkulasi dikirimkan via channel yang sudah dipersiapkan, yaitu ch1
untuk menampung data rata-rata, ch2
untuk data nilai tertinggi.
Ok lanjut, buat implementasinya pada fungsi main()
.
func main() {
runtime.GOMAXPROCS(2)
var numbers = []int{3, 4, 3, 5, 6, 3, 2, 2, 6, 3, 4, 6, 3}
fmt.Println("numbers :", numbers)
var ch1 = make(chan float64)
go getAverage(numbers, ch1)
var ch2 = make(chan int)
go getMax(numbers, ch2)
for i := 0; i < 2; i++ {
select {
case avg := <-ch1:
fmt.Printf("Avg \t: %.2f \n", avg)
case max := <-ch2:
fmt.Printf("Max \t: %d \n", max)
}
}
}
Pada kode di atas, pengiriman data pada channel ch1
dan ch2
dikontrol menggunakan select
. Terdapat 2 buah case
kondisi penerimaan data dari kedua channel tersebut.
- Kondisi
case avg := <-ch1
akan terpenuhi ketika ada penerimaan data dari channelch1
, yang kemudian akan ditampung oleh variabelavg
. - Kondisi
case max := <-ch2
akan terpenuhi ketika ada penerimaan data dari channelch2
, yang kemudian akan ditampung oleh variabelmax
.
Karena ada 2 buah channel, maka perlu disiapkan perulangan 2 kali sebelum penggunaan keyword select
.
Cukup mudah bukan?