Mengenal Package Context With Cancel Pada Golang
Pengenalan package context.WithCancel
Context yang bisa menambahkan value, kita juga bisa menambahkan sinyal cancel ke dalam context. Biasanya context cancel ini dipakai saat kita butuh menjalankan proses lain, dan kita ingin memberi cancel ke proses tersebut. context cancel ini dijalankan biasanya menggunakan goroutine yang berbeda sehingga dengan mudah kita ingin membatalkan proses eksekusi goroutine tersebut, jadi tingal kita kirim sinyal cancel ke dalam context maka goroutine yang ingin kita stop sudah bisa kita lakukan.
Kenapa kita harus menggunakan context?
Context.WithCancel ini kita gunakan untuk membatasi proses ketika kita ingin menghentikan proses tersebut di suatu goroutine dan kita ingin melanjutkan proses ke proses selanjutnya atau proses yang lain. Jika kita ingin membuat context dengan sinyal cancel, maka kita perlu menggunakan fungsi context.WithCancel(parent).
Implementasi dan sampel
Sebelum ke implementasi context.WithCancel, kita akan simulasikan terlebih dahulu bagaimana ketika kode program kita terjadi memory leak. Berikut dibawah ini kodenya.
Kita akan mengimplementasikannya dengan sampel kode dibawah ini.
1func main() {
2 fmt.Println("Total Goroutine ", runtime.NumGoroutine())
3 destination := CreateCounter()
4 for n := range destination {
5 fmt.Println("Counter ", n)
6 if n == 10 {
7 break
8 }
9 }
10 fmt.Println("Total Goroutine ", runtime.NumGoroutine())
11}
12
13func CreateCounter() chan int {
14 destination := make(chan int)
15 go func() {
16 defer close(destination)
17 counter := 1
18 for {
19 destination <- counter
20 counter++
21 }
22 }()
23 return destination
24}counter dengan menggunakan satu goroutine ketika dipanggil di main fungsi. Pada main program kita akan menjalankan 10 counter saja agar tidak terlalu banyak saat dilakukan cetak ke terminal.
Maka alhasil ketika kita jalankan program tersebut akan mencetak seperti dibawah ini. 1✗ go run app.go
2Total Goroutine 1
3Counter 1
4Counter 2
5Counter 3
6Counter 4
7Counter 5
8Counter 6
9Counter 7
10Counter 8
11Counter 9
12Counter 10
13Total Goroutine 2memory leak.Maka kita perlu mekanisme menghapus atau menghentikan proses goroutine yang sudah tidak terpakai. Bagaimana caranya? Yaitu salah satunya bisa dengan menggunakan context.WithCancel.
Lalu, bagaimana cara mengimplementasikan context.WithCancel pada kode program sebelumnya? Baiklah kita lihat kode program yang sudah diperbaiki dengan menambahkan context.WithCancel dibawah ini.
1func main() {
2 parent := context.Background() // context parent
3 ctx, cancel := context.WithCancel(parent) // context child with cancel
4
5 fmt.Println("Total Goroutine ", runtime.NumGoroutine())
6
7 destination := CreateCounter(ctx)
8 for n := range destination {
9 fmt.Println("Counter ", n)
10 if n == 10 {
11 break
12 }
13 }
14 cancel()
15
16 time.Sleep(3 * time.Second)
17 fmt.Println("Total Goroutine ", runtime.NumGoroutine())
18}
19
20func CreateCounter(ctx context.Context) chan int {
21 destination := make(chan int)
22 go func() {
23 defer close(destination)
24 counter := 1
25 for {
26 select {
27 case <-ctx.Done():
28 return
29 default:
30 destination <- counter
31 counter++
32 }
33 }
34 }()
35 return destination
36}Penambahan pada kode diatas yaitu kita akan mengirimkan context pada fungsi menggunakan parameter. Lalu context tersebut kita pakai pada goroutine dan kita tambahkan seleksi select yang mana ini digunakan untuk memastikan ketika proses pada fungsi main memanggil untuk cancel() maka proses goroutine pun akan berhenti dan menghapus proses tersebut dalam memori.
Maka kita coba jalankan program setelah perbaikan dengan hasil dibawah ini.
1✗ go run app.go
2Total Goroutine 1
3Counter 1
4Counter 2
5Counter 3
6Counter 4
7Counter 5
8Counter 6
9Counter 7
10Counter 8
11Counter 9
12Counter 10
13Total Goroutine 1cancel() maka proses tersebut akan berhenti otomatis goroutine-nya pun akan berhenti dan menghapus dari memori.Kesimpulan
context.WithCancel sangat perlu sekali digunakan jika kita menjalankan proses-proses secara paralel ataupun tidak bahkan ini menjadi suatu kewajiban bagi para developer golang agar tiap passing parameter dalam fungsi ditambahkan context agar bisa melakukan cancel proses, dan menghindari dari goroutine yang terus berjalan tanpa digunakan karena prosesnya tidak diberhentikan.