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.
Concurrency adalah kemampuan menjalankan banyak task secara bersamaan (not necessarily parallel). Misalnya:
Di Golang, concurrency difasilitasi dengan goroutines dan channels.
Goroutine adalah lightweight thread yang dijalankan oleh Go runtime. Untuk membuat goroutine, cukup gunakan keyword go di depan fungsi.
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.
Channel digunakan untuk komunikasi antar goroutine. Dengan channel, kita bisa mengirim dan menerima data dengan aman tanpa khawatir race condition.
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.
Channel bisa dibuat buffered, artinya bisa menampung sejumlah data sebelum harus dibaca.
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.
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
Dengan pemahaman ini, kamu bisa mulai membangun aplikasi Go yang lebih cepat dan efisien.