Channel — Go

Channel Channel adalah cara utama goroutine berkomunikasi satu sama lain. Prinsip Go: "Do not communicate by sharing memory; instead, share memory by…

Channel adalah saluran bertipe untuk mengirim nilai dari satu goroutine ke goroutine lain. Bayangin antrean pesanan antara kasir dan dapur Warung Bakso Mas Bimo. Kasir (satu goroutine) memasukkan pesanan, dapur (goroutine lain) mengambilnya. Ada dua jenis antrean: tanpa nampan, kasir harus menyerahkan mangkuk langsung ke tangan juru masak, jadi keduanya harus ketemu dulu; dengan nampan berisi 3 tempat, kasir boleh menaruh sampai 3 pesanan lalu kembali ke pembeli. Itu channel unbuffered dan buffered. Prinsip Go: "jangan berkomunikasi dengan berbagi memori, bagilah memori dengan berkomunikasi".

🧪 Tebakan cepat: antrean := make(chan string), lalu main langsung menjalankan antrean <- "bakso urat" tanpa ada goroutine lain. Apa yang terjadi? Tebak dulu, jawabannya ada di bagian "Unbuffered: harus ketemu".

Membuat, mengirim, menerima

package main

import "fmt"

func main() {
	antrean := make(chan string)
	go func() {
		antrean <- "bakso urat"
	}()
	pesanan := <-antrean
	fmt.Println("dapur terima:", pesanan)
}
$ go run bakso.go
dapur terima: bakso urat

Unbuffered: harus ketemu

Channel dari make(chan string) gak punya tempat menyimpan. Pengirim menunggu sampai ada penerima, dan penerima menunggu sampai ada pengirim. Begitu keduanya siap, nilainya pindah, dan dua-duanya lanjut.

Di tebakan tadi, satu-satunya goroutine adalah main, dan ia sendiri yang menunggu di baris kirim. Gak ada yang akan pernah menerima:

$ go run bakso.go
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
	/home/bimo/bakso/bakso.go:7 +0x28
exit status 2

Deadlock: semua goroutine saling menunggu dan gak ada yang bisa jalan. Runtime Go mendeteksinya, menyebut goroutine yang macet beserta alasannya (chan send), lalu menghentikan program. Itu jawaban tebakannya.

Buffered: nampan berkapasitas

antrean := make(chan string, 3)
antrean <- "bakso urat"
antrean <- "mie ayam"
antrean <- "es teh"
fmt.Println("isi:", len(antrean), "kapasitas:", cap(antrean)) // isi: 3 kapasitas: 3
antrean <- "bakso urat"
make(chan string) make(chan string, 3)
Kirim menunggu kalau belum ada penerima buffer penuh (3 isi)
Terima menunggu kalau belum ada pengirim buffer kosong
Cocok untuk titik temu, sinyal "sudah diterima" menaruh dulu, sampai batas tertentu

close dan range

Pengirim menutup channel dengan close saat sudah gak ada yang mau dikirim. Penerima bisa memakai range untuk mengambil semua isinya sampai channel ditutup:

func kasir(antrean chan<- string) {
	for _, menu := range []string{"bakso urat", "mie ayam", "es teh"} {
		fmt.Println("kasir kirim:", menu)
		antrean <- menu
	}
	close(antrean)
}

func main() {
	antrean := make(chan string)
	go kasir(antrean)
	for menu := range antrean {
		fmt.Println("dapur masak:", menu)
	}
	fmt.Println("antrean kosong, dapur istirahat")
}
$ go run bakso.go
kasir kirim: bakso urat
kasir kirim: mie ayam
dapur masak: bakso urat
dapur masak: mie ayam
kasir kirim: es teh
dapur masak: es teh
antrean kosong, dapur istirahat

📌 Arah channel di parameter

func kasir(antrean chan<- string) artinya kasir cuma boleh mengirim. <-chan string berarti cuma boleh menerima. Compiler menolak kalau dilanggar: menerima dari chan<- string gagal dengan invalid operation: cannot receive from send-only channel antrean (variable of type chan<- string). Ini membuat peran tiap fungsi jelas dari tanda tangannya.

⚠️ Jebakan yang sering ketemu

TL;DR: Channel mengirim nilai antar goroutine: antrean := make(chan string), kirim dengan antrean <- "bakso urat", terima dengan m := <-antrean. Unbuffered (make(chan T)): pengirim menunggu sampai penerima siap. Buffered (make(chan T, 3)): pengirim baru menunggu kalau buffer penuh. Kalau semua goroutine saling menunggu, program mati dengan fatal error: all goroutines are asleep - deadlock!. Pengirim menutup channel dengan close, range membaca sampai channel ditutup, dan menerima dari channel tertutup yang kosong memberi zero value dengan ok == false. Kirim ke channel tertutup atau close dua kali bikin panic.

Yang akan kamu pelajari