5 Concurrency Patterns di Golang

Cecep Aprilianto
3 min readJul 28, 2024

--

worker illustration

Concurrency patterns sangat penting dalam pengembangan aplikasi yang membutuhkan performa tinggi dan efisiensi. Berikut beberapa concurrency patterns yang umum digunakan di Golang

1. Worker Pool

  • Deskripsi: Membuat sejumlah worker goroutine yang mengambil setiap pekerjaan dari sebuah kanal.
  • Kegunaan: Cocok untuk membatasi jumlah goroutine yang berjalan secara bersamaan saat memproses pekerjaan yang banyak.

Example Code:

package main

import (
"fmt"
"sync"
)

func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Println("worker", id, "started job", j)
results <- j * 2
fmt.Println("worker", id, "finished job", j)
}
}

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

for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}

for j := 1; j <= numJobs; j++ {
jobs <- j
}
close(jobs)

for a := 1; a <= numJobs; a++ {
<-results
}
}

2. Pipeline

  • Deskripsi: Memproses data melalui serangkaian tahap yang dijalankan secara concurrent.
  • Kegunaan: Berguna untuk memproses data dalam beberapa tahap, seperti validasi, transformasi, dan penyimpanan.

Example Code:

package main

import "fmt"

func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}

func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}

func main() {
c := gen(2, 3, 4)
out := sq(c)

for n := range out {
fmt.Println(n)
}
}

3. Fan-out, Fan-in

  • Deskripsi: Fan-out adalah pola di mana satu goroutine mendistribusikan job ke beberapa goroutine lainnya. Fan-in mengumpulkan hasil dari beberapa goroutine ke satu goroutine.
  • Kegunaan: Berguna untuk memanfaatkan banyak CPU core dengan membagi pekerjaan besar menjadi pekerjaan kecil.

Example Code:

package main

import (
"fmt"
"sync"
)

func main() {
in := gen(2, 3, 4, 5)

c1 := sq(in)
c2 := sq(in)

for n := range merge(c1, c2) {
fmt.Println(n)
}
}

func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}

func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}

func merge(cs ...<-chan int) <-chan int {
var wg sync.WaitGroup
out := make(chan int)

output := func(c <-chan int) {
for n := range c {
out <- n
}
wg.Done()
}

wg.Add(len(cs))
for _, c := range cs {
go output(c)
}

go func() {
wg.Wait()
close(out)
}()
return out
}

4. Select Statement

  • Deskripsi: Memilih di antara beberapa operasi channel yang siap untuk dijalankan.
  • Kegunaan: Berguna untuk menangani beberapa channel sekaligus dalam sebuah goroutine.

Example Code:

package main

import (
"fmt"
"time"
)

func main() {
ch1 := make(chan string)
ch2 := make(chan string)

go func() {
time.Sleep(2 * time.Second)
ch1 <- "one"
}()

go func() {
time.Sleep(1 * time.Second)
ch2 <- "two"
}()

for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("received", msg1)
case msg2 := <-ch2:
fmt.Println("received", msg2)
}
}
}

5. Context

  • Deskripsi: Menggunakan context untuk mengelola timeout, cancel, dan cross data API dan goroutine.
  • Kegunaan: Berguna untuk mengontrol eksekusi goroutine terutama pada web service atau API yang harus menangani permintaan yang mungkin memakan waktu lama atau terputus di tengah jalan.

Example Code:

package main

import (
"context"
"fmt"
"time"
)

func main() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

ch := make(chan string)
go func() {
time.Sleep(2 * time.Second)
ch <- "operation result"
}()

select {
case res := <-ch:
fmt.Println(res)
case <-ctx.Done():
fmt.Println("operation timed out")
}
}

Dengan memahami dan menerapkan concurrency pattern di atas, kalian bisa menulis kode yang lebih efisien dan dapat diskalakan dengan lebih baik dalam Golang.

--

--

Cecep Aprilianto
Cecep Aprilianto

Written by Cecep Aprilianto

Web and Backend Developer at Internet

No responses yet