Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 60 additions & 2 deletions intermediate/concurrency/goroutines/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,69 @@ Selanjutnya, mari kita perhatikan goroutine `go alphabets()` dan `go numbers()`.
## Mendeklarasikan Channel
Berikut cara mendeklarasikan, mengirim dan menerima data dari channel (kode diambil dari [https://golangbot.com/channels/](https://golangbot.com/channels/))

### unbuffered channel
```Go
a := make(chan int) // mendeklarasikan channel dengan tipe data integer
```

### buffered channel
channel juga dapat memiliki kapasitas (buffered), cukup dengan menspesifikasikan kapasitas/panjang data pada argument kedua fungsi make()
```go
// buffered channel dengan kapasitas 10
b := make(chan int, 10)
```

buffered channel dapat digunakan untuk proses asinkron dimana data dapat disimpan dahulu hingga kapasitas penuh sebelum dikonsumsi goroutine lain.

## Range dan close
Pengirim dapat menutup (close) channel untuk mengindikasikan bahwa tidak ada lagi value yang akan dikirim. Penerima dapat mengecek apakah channel sudah ditutup dengan meng-*assign* argumen kedua. [sumber](https://go.dev/tour/concurrency/4)
```go
v, ok := <-a
```
ok adalah false jika tidak ada lagi value yang diterima dan channel ditutup

channel juga dapat diiterasi menggunakan for loop:

```go
for val := range a
```
ia menerima value dari channel secara terus menerus hingga channel ditutup

## data flow
Seperti terlihat pada contoh code sebelumnya, dapat dilihat bahwa data pada channel mengalir berdasarkan arah panah

### contoh
```go
chan1 := make(chan int)
num := 1
chan1 <- num // chan1 menerima (receive) data dari variabel num
var out int
out := <- chan1 // chan1 mengirim (send) data ke variabel out
```

data := <- a // mengirim data dari channel a dan menyimpan hasilnya ke dalam variabel data
a <- data // channel a menerima data dari variabel data
### contoh data flow data channel pada parameter fungsi
```go
// contoh fungsi dengan parameter channel yang hanya menerima data channel
func terima(data <-chan int) {
receive := <-data
num := 1
fmt.Printf("%d\n", receive)
}

// contoh fungsi dengan parameter channel yang hanya mengirim data ke channel
func kirim(data chan<- int) {
num := 1
data <- num
close(data)
// NOTE: channel sebaiknya ditutup dari sisi pengirim
// untuk menghindari goroutine penerima menunggu terus (deadlock)
}

// contoh fungsi dengan parameter channel yang dapat mengirim maupun menerima data pada channel (bidirectional)
func duaArrah(dataChan chan int) {
num := <-dataChan
dataChan <- num
}
```

## Contoh Penggunaan Channel
Expand Down
61 changes: 61 additions & 0 deletions intermediate/concurrency/goroutines/contoh_channel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package main

import (
"fmt"
"math/rand"
"sync"
"time"
)

type Order struct {
Id int
status string
}

func generateOrder(n int) []*Order {
orders := []*Order{}

for i := range n {
order := Order{
Id: i + 1,
status: "pending",
}
orders = append(orders, &order)
}

return orders
}

func processOrder(orderChan <-chan *Order, wg *sync.WaitGroup) {
defer wg.Done()
// loop berikut menerima value dari channel terus menerus hingga ditutup.
for order := range orderChan {
time.Sleep(time.Duration(rand.Intn(500)+10) * time.Millisecond)
status := []string{"delivered", "shipped"}[rand.Intn(2)]
order.status = status
fmt.Printf("procssing order: %d with status: %s\n", order.Id, order.status)
}
}

func main() {
var wg sync.WaitGroup
wg.Add(2)

n := 20
orderChan := make(chan *Order, n)

go func() {
wg.Done()
for _, order := range generateOrder(n) {
orderChan <- order
}
// karena kita mengirim data ke channel pada function ini, maka kita dapat panggil fungsi close di sini
close(orderChan)
fmt.Printf("done generating order\n")
}()

go processOrder(orderChan, &wg)

wg.Wait()
fmt.Printf("All operation is done!\n")
}