Concurrency di Golang: Goroutines & Channels

Salah satu kekuatan terbesar dari Golang adalah dukungan concurrency yang sederhana namun powerful. Dengan fitur goroutines dan channels, kita dapat menulis program paralel yang efisien tanpa harus pusing dengan thread management secara manual.


Apa itu Concurrency?

Concurrency adalah kemampuan menjalankan banyak task secara bersamaan (not necessarily parallel). Misalnya:

  • Download beberapa file sekaligus.
  • Memproses request HTTP dalam jumlah besar.
  • Menjalankan worker pool untuk job queue.

Di Golang, concurrency difasilitasi dengan goroutines dan channels.


Goroutines

Goroutine adalah lightweight thread yang dijalankan oleh Go runtime. Untuk membuat goroutine, cukup gunakan keyword go di depan fungsi.

Contoh 1: Hello Goroutine

package main

import (
    "fmt"
    "time"
)

func printMessage(msg string) {
    for i := 0; i < 5; i++ {
        fmt.Println(msg, i)
        time.Sleep(500 * time.Millisecond)
    }
}

func main() {
    go printMessage("Hello from Goroutine")
    printMessage("Hello from Main")
}

Output akan bercampur karena keduanya berjalan bersamaan.


Channels

Channel digunakan untuk komunikasi antar goroutine. Dengan channel, kita bisa mengirim dan menerima data dengan aman tanpa khawatir race condition.

Contoh 2: Channel Dasar

package main

import "fmt"

func main() {
    ch := make(chan string)

    go func() {
        ch <- "Hello from Goroutine"
    }()

    msg := <-ch
    fmt.Println(msg)
}

Di sini, goroutine mengirim string ke channel, lalu main goroutine menerima data tersebut.


Buffered Channels

Channel bisa dibuat buffered, artinya bisa menampung sejumlah data sebelum harus dibaca.

Contoh 3: Buffered Channel

package main

import "fmt"

func main() {
    ch := make(chan int, 3)

    ch <- 1
    ch <- 2
    ch <- 3

    fmt.Println(<-ch)
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}

Jika buffer penuh, goroutine akan blok sampai ada yang membaca channel.


Worker Pool dengan Goroutines & Channels

Studi kasus sederhana: kita punya daftar angka, dan ingin menghitung kuadratnya secara paralel.

package main

import (
    "fmt"
    "sync"
)

func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    for j := range jobs {
        fmt.Printf("Worker %d processing job %d\n", id, j)
        results <- j * j
    }
}

func main() {
    jobs := make(chan int, 5)
    results := make(chan int, 5)

    var wg sync.WaitGroup

    // Jalankan 3 worker
    for w := 1; w <= 3; w++ {
        wg.Add(1)
        go worker(w, jobs, results, &wg)
    }

    // Kirim 5 job
    for j := 1; j <= 5; j++ {
        jobs <- j
    }
    close(jobs)

    // Tunggu semua worker selesai
    go func() {
        wg.Wait()
        close(results)
    }()

    // Ambil hasil
    for r := range results {
        fmt.Println("Result:", r)
    }
}

Output:

Worker 1 processing job 1
Worker 2 processing job 2
Worker 3 processing job 3
Worker 1 processing job 4
Worker 2 processing job 5
Result: 1
Result: 4
Result: 9
Result: 16
Result: 25

Kesimpulan

  • Goroutine adalah thread ringan untuk menjalankan fungsi secara bersamaan.
  • Channel memungkinkan komunikasi antar goroutine dengan cara aman.
  • Concurrency di Go sangat cocok untuk membangun aplikasi dengan banyak proses paralel, seperti API server, worker pool, hingga sistem distributed.

Dengan pemahaman ini, kamu bisa mulai membangun aplikasi Go yang lebih cepat dan efisien.