🖥️ VS Code: Visualisasi Goroutine saat Debug
Saat debugging Go di VS Code (tekan F5), panel Goroutines di sidebar kiri menampilkan semua goroutine yang sedang berjalan beserta status-nya. Sangat berguna untuk mendeteksi goroutine yang deadlock. Pastikan extension Go by Google sudah terinstall.
Concurrency adalah kemampuan menjalankan banyak tugas secara bersamaan. Go memiliki fitur concurrency built-in yang sangat ringan — kamu bisa menjalankan ribuan goroutine sekaligus tanpa masalah memori yang serius.
Apa itu Goroutine?
Goroutine adalah fungsi yang berjalan secara konkuren (bersamaan) dengan goroutine lain. Berbeda dengan thread OS yang berat, goroutine sangat ringan — hanya sekitar 2KB memori saat pertama dibuat, dan Go runtime yang mengatur penjadwalannya.
package main
import (
"fmt"
"time"
)
func tugasA() {
for i := 0; i < 3; i++ {
fmt.Println("Tugas A:", i)
time.Sleep(100 * time.Millisecond)
}
}
func tugasB() {
for i := 0; i < 3; i++ {
fmt.Println("Tugas B:", i)
time.Sleep(100 * time.Millisecond)
}
}
func main() {
go tugasA() // jalankan sebagai goroutine
go tugasB() // jalankan sebagai goroutine
time.Sleep(1 * time.Second) // tunggu goroutine selesai
}
time.Sleep untuk menunggu goroutine adalah cara yang tidak tepat. Pakai sync.WaitGroup atau channel.
sync.WaitGroup
WaitGroup dipakai untuk menunggu sekumpulan goroutine selesai:
package main
import (
"fmt"
"sync"
)
func proses(id int, wg *sync.WaitGroup) {
defer wg.Done() // kurangi counter saat selesai
fmt.Printf("Goroutine %d selesai\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1) // tambah counter
go proses(i, &wg) // jalankan goroutine
}
wg.Wait() // tunggu semua goroutine selesai
fmt.Println("Semua selesai!")
}
Channel
Channel adalah "pipa" untuk mengirim data antar goroutine dengan aman. Ini cara idiomatik Go untuk komunikasi antar goroutine.
// Buat channel
ch := make(chan int)
// Kirim data ke channel (dalam goroutine)
go func() {
ch <- 42 // kirim nilai 42
}()
// Terima data dari channel
nilai := <-ch
fmt.Println(nilai) // 42
Contoh nyata — hitung di goroutine, kirim hasilnya:
func hitungKuadrat(angka int, ch chan int) {
ch <- angka * angka
}
func main() {
ch := make(chan int)
go hitungKuadrat(4, ch)
go hitungKuadrat(5, ch)
a, b := <-ch, <-ch
fmt.Println(a, b) // 16 25 (urutan bisa berbeda)
}
Buffered Channel
Channel biasa bersifat blocking — pengirim menunggu penerima siap. Buffered channel punya antrian internal:
// Buffered channel dengan kapasitas 3
ch := make(chan string, 3)
ch <- "pesan 1" // tidak blocking
ch <- "pesan 2" // tidak blocking
ch <- "pesan 3" // tidak blocking
// ch <- "pesan 4" // ini akan blocking karena penuh
fmt.Println(<-ch) // "pesan 1"
fmt.Println(<-ch) // "pesan 2"
Select
select memungkinkan goroutine menunggu beberapa channel sekaligus, mengeksekusi case yang pertama kali siap:
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() { ch1 <- "dari ch1" }()
go func() { ch2 <- "dari ch2" }()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
}
}
}
Done Pattern (Cancel Goroutine)
Cara umum untuk menghentikan goroutine yang berjalan lama:
func worker(done <-chan bool) {
for {
select {
case <-done:
fmt.Println("Worker berhenti")
return
default:
fmt.Println("Worker bekerja...")
}
}
}
func main() {
done := make(chan bool)
go worker(done)
time.Sleep(3 * time.Second)
done <- true // kirim sinyal berhenti
}
Mutex: Proteksi Data Bersama
Ketika beberapa goroutine mengakses variabel yang sama, gunakan mutex untuk mencegah race condition:
package main
import (
"fmt"
"sync"
)
type Counter struct {
mu sync.Mutex
nilai int
}
func (c *Counter) Tambah() {
c.mu.Lock()
defer c.mu.Unlock()
c.nilai++
}
func main() {
counter := &Counter{}
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
counter.Tambah()
}()
}
wg.Wait()
fmt.Println("Nilai:", counter.nilai) // pasti 1000
}
"Do not communicate by sharing memory; instead, share memory by communicating."
Artinya: daripada beberapa goroutine mengakses variabel yang sama (butuh mutex), lebih baik kirim data melalui channel. Channel adalah cara idiomatik dan lebih aman.
Komentar 0