Goroutine & WaitGroup
Menjalankan pekerjaan bersamaan dengan go dan menunggunya dengan sync.WaitGroup.
Konkurensi di Go
Banyak program perlu mengerjakan beberapa hal sekaligus: melayani ribuan pengguna, mengunduh banyak file, memanggil beberapa API. Go membuat ini mudah lewat goroutine.
goroutine
Awali pemanggilan function dengan go dan function itu berjalan di latar belakang secara konkuren:
go cetak("A") // jalan konkuren
cetak("B") // jalan di goroutine utama
Goroutine sangat ringan (awalnya sekitar 2 KB), sehingga aman membuat puluhan ribu sekaligus. Go runtime yang menjadwalkannya ke beberapa thread OS.
Masalah: main tidak menunggu
Saat main selesai, seluruh program berhenti — termasuk goroutine yang belum selesai:
func main() {
go fmt.Println("tidak akan sempat tampil")
}
sync.WaitGroup
Penghitung untuk menunggu sekumpulan goroutine selesai:
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1) // tambah penghitung SEBELUM menjalankan goroutine
go func(n int) {
defer wg.Done() // kurangi penghitung saat selesai
fmt.Println("worker", n, "selesai")
}(i)
}
wg.Wait() // blok sampai penghitung = 0
Add(n)— menambah n pekerjaan.Done()— menandai satu pekerjaan selesai.Wait()— menunggu semuanya.
Hati-hati: variable loop
Kirim variable loop sebagai argumen ke goroutine (seperti (i) di atas), agar setiap goroutine memiliki salinan sendiri. (Mulai Go 1.22 perilaku ini sudah lebih aman, tetapi kebiasaan ini tetap baik.)
Urutan tidak pasti
Goroutine tidak punya urutan eksekusi yang terjamin. Jika hasilmu perlu berurutan, kumpulkan hasilnya lalu urutkan, atau gunakan channel (bab berikutnya).
Data race
Dua goroutine yang menulis ke variable yang sama tanpa sinkronisasi menyebabkan race condition. Lindungi dengan sync.Mutex:
var mu sync.Mutex
mu.Lock()
saldo += 10
mu.Unlock()
Gunakan go run -race atau go test -race untuk mendeteksinya.