Skip to content

Commit e11757b

Browse files
authored
chore: menambah penjelasan tentang channel dan membuat contoh penerapan channel (#66)
* docs: menambahkan penjelasan terkait channel * chore: menambahkan contoh penerapan channel
1 parent 36caf49 commit e11757b

File tree

2 files changed

+121
-2
lines changed

2 files changed

+121
-2
lines changed

intermediate/concurrency/goroutines/README.md

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,69 @@ Selanjutnya, mari kita perhatikan goroutine `go alphabets()` dan `go numbers()`.
149149
## Mendeklarasikan Channel
150150
Berikut cara mendeklarasikan, mengirim dan menerima data dari channel (kode diambil dari [https://golangbot.com/channels/](https://golangbot.com/channels/))
151151

152+
### unbuffered channel
152153
```Go
153154
a := make(chan int) // mendeklarasikan channel dengan tipe data integer
155+
```
156+
157+
### buffered channel
158+
channel juga dapat memiliki kapasitas (buffered), cukup dengan menspesifikasikan kapasitas/panjang data pada argument kedua fungsi make()
159+
```go
160+
// buffered channel dengan kapasitas 10
161+
b := make(chan int, 10)
162+
```
163+
164+
buffered channel dapat digunakan untuk proses asinkron dimana data dapat disimpan dahulu hingga kapasitas penuh sebelum dikonsumsi goroutine lain.
165+
166+
## Range dan close
167+
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)
168+
```go
169+
v, ok := <-a
170+
```
171+
ok adalah false jika tidak ada lagi value yang diterima dan channel ditutup
172+
173+
channel juga dapat diiterasi menggunakan for loop:
174+
175+
```go
176+
for val := range a
177+
```
178+
ia menerima value dari channel secara terus menerus hingga channel ditutup
179+
180+
## data flow
181+
Seperti terlihat pada contoh code sebelumnya, dapat dilihat bahwa data pada channel mengalir berdasarkan arah panah
182+
183+
### contoh
184+
```go
185+
chan1 := make(chan int)
186+
num := 1
187+
chan1 <- num // chan1 menerima (receive) data dari variabel num
188+
var out int
189+
out := <- chan1 // chan1 mengirim (send) data ke variabel out
190+
```
154191

155-
data := <- a // mengirim data dari channel a dan menyimpan hasilnya ke dalam variabel data
156-
a <- data // channel a menerima data dari variabel data
192+
### contoh data flow data channel pada parameter fungsi
193+
```go
194+
// contoh fungsi dengan parameter channel yang hanya menerima data channel
195+
func terima(data <-chan int) {
196+
receive := <-data
197+
num := 1
198+
fmt.Printf("%d\n", receive)
199+
}
200+
201+
// contoh fungsi dengan parameter channel yang hanya mengirim data ke channel
202+
func kirim(data chan<- int) {
203+
num := 1
204+
data <- num
205+
close(data)
206+
// NOTE: channel sebaiknya ditutup dari sisi pengirim
207+
// untuk menghindari goroutine penerima menunggu terus (deadlock)
208+
}
209+
210+
// contoh fungsi dengan parameter channel yang dapat mengirim maupun menerima data pada channel (bidirectional)
211+
func duaArrah(dataChan chan int) {
212+
num := <-dataChan
213+
dataChan <- num
214+
}
157215
```
158216

159217
## Contoh Penggunaan Channel
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"math/rand"
6+
"sync"
7+
"time"
8+
)
9+
10+
type Order struct {
11+
Id int
12+
status string
13+
}
14+
15+
func generateOrder(n int) []*Order {
16+
orders := []*Order{}
17+
18+
for i := range n {
19+
order := Order{
20+
Id: i + 1,
21+
status: "pending",
22+
}
23+
orders = append(orders, &order)
24+
}
25+
26+
return orders
27+
}
28+
29+
func processOrder(orderChan <-chan *Order, wg *sync.WaitGroup) {
30+
defer wg.Done()
31+
// loop berikut menerima value dari channel terus menerus hingga ditutup.
32+
for order := range orderChan {
33+
time.Sleep(time.Duration(rand.Intn(500)+10) * time.Millisecond)
34+
status := []string{"delivered", "shipped"}[rand.Intn(2)]
35+
order.status = status
36+
fmt.Printf("procssing order: %d with status: %s\n", order.Id, order.status)
37+
}
38+
}
39+
40+
func main() {
41+
var wg sync.WaitGroup
42+
wg.Add(2)
43+
44+
n := 20
45+
orderChan := make(chan *Order, n)
46+
47+
go func() {
48+
wg.Done()
49+
for _, order := range generateOrder(n) {
50+
orderChan <- order
51+
}
52+
// karena kita mengirim data ke channel pada function ini, maka kita dapat panggil fungsi close di sini
53+
close(orderChan)
54+
fmt.Printf("done generating order\n")
55+
}()
56+
57+
go processOrder(orderChan, &wg)
58+
59+
wg.Wait()
60+
fmt.Printf("All operation is done!\n")
61+
}

0 commit comments

Comments
 (0)