Channel

Pada sesi ini kita masih membahas tentang concurrency pada Go yaitu channel

Channel adalah tipe data yang dapat membuat Goroutine saling bertukar informasi atau saling berkomunikasi (send and receive). Channel juga membuat Goroutine menjadi Blocking dan Synchronized.

Untuk membuat sebuah Channel, kita dapat menggunakan make seperti berikut ini:

ch := make(chan int) // Membuat channel dengan tipe integer

atau

var ch chan int // Membuat channel dengan tipe integer

Operator yang digunakan untuk mengirim dan menerima nilai dengan Channel menggunakan <- :

ch <- v    // Send v to channel ch.

v := <-ch  // Receive from ch, and
           // assign value to v.

Studi Kasus #1

Pada studi kasus pertama kita akan membuat 1 buah fungsi untuk menghitung total numbers dari slice . Lalu membuat 1 buah fungsi sebagai main . Dua fungsi tersebut akan kita anggap sebagai Goroutines.

Fungsi main secara implisit juga termasuk Goroutines

package main

import "fmt"

func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum // send sum to c
}

func main() {
	s := []int{7, 2, 8, -9, 4, 0}

	c := make(chan int)
	go sum(s[0:3], c)
	go sum(s[1:5], c)
	x, y := <-c, <-c // receive from c

	fmt.Println(x, y, x+y)
}

Pada kode di atas fungsi sum berperan sebagai goroutine yang mengirim data melalui Channel. Ini ditandai dengan penggunaan operator c <- sum .

Sementara itu fungsi main berperan sebagai goroutine yang menerima nilai melalui Channel. Ini ditandai dengan penggunaan operator x, y := <-c, <-c .

Kita bisa lihat dari output proses yang terjadi adalah:

5 -> berasal dari proses go sum(s[1:5], c)
17 -> berasal dari proses go sum(s[0:3], c)
22 -> berasal dari proses penambahan di dalam fmt.Println()

Ini membuktikan bahwa goroutines berjalan Asynchronous.

Namun proses Channel bersifat Synchronous. Ini bisa dilihat bahwa program akan menunggu proses nilai yang dikirim melalui Channel selesai terlebih dahulu yaitu:

x, y := <-c, <-c // receive from c

baru menjalankan proses di bawahnya:

fmt.Println(x, y, x+y)

Jadi Channel dapat menjadikan proses Goroutine menjadi Synchronous.

Studi Kasus #2

Pada studi kasus ke-2 ini kita akan membuat 2 fungsi secara independen yang berperan sebagai pengirim dan penerima nilai melalui Channel. Kita hanya menjadikan fungsi main sebagai tempat memanggil goroutine.

package main

import (
	"fmt"
)

func main() {
	c := make(chan int)
	s := []int{2, 2, 2, 2, 2}

	go sum(s, c)
	go result(c)

	var input string
	fmt.Scanln(&input)
}

// Fungsi sum berperan sebagai pengirim nilai melalui Channel
func sum(s []int, c chan int) {
	total := 0
	for _, v := range s {
		total += v
	}
	c <- total
}

// Fungsi result berperan sebagai penerima nilai melalui Channel
func result(c chan int) {
	result := <-c
	fmt.Println(result)
}

Pada kode di atas kita bisa melihat bahwa pada fungsi main , kita menggunakan bantuan fmt.Scanln untuk blocking program karena kemungkinan fungsi yang dijalankan sebagai goroutine selesai lebih lama daripada program di dalam fungsi main .

Last updated