Pipeline adalah metode virtual untuk menghubungkan goroutine dan channel, sehingga output dari salah satu goroutine menjadi input untuk goroutine lainnya menggunakan channel untuk memindahkan data.
Keuntungan menggunakan pipeline adalah aliran data pada program kita selalu konstan, dimana kita tidak perlu menunggu setiap goroutine untuk menyelesaikan tugasnya.
Kerangka program
Program yang akan kita buat terdiri dari 4 fungsi, dimana dua fungsi akan kita gunakan sebagai goroutine (buatRandomData()
dan cekDataDuplikat()
), sedangkan tampilData()
akan kita gunakan sebagai fungsi biasa dan akan dipanggil pada fungsi utama main()
.
Disini kita juga mendefinisikan dua variabel DATA
untuk mengecek apakah ada data yang sama dengan data yang sudah dibuat dan variabel TutupChannelA
untuk menutup channel. Variabel TutupChannelA
digunakan untuk menutup channel utama ketika ada data yang sama.
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
var TutupChannelA = false
var DATA = make(map[int]bool)
// menulis random data ke channel
func buatRandomData(min, max int, output chan<- int) {
}
// cek data duplikat, membaca dan menulis data ke channel
func cekDataDuplikat(input <-chan int, output chan<- int) {
}
// membaca data dari channel dan menjumlahkan nilainya
func tampilData(input <-chan int) {
}
//fungsi utama
func main() {
}
Cara kerja utama program
Program kita akan membutuhkan dua input integer (argumen1
dan argumen2
) untuk selanjutnya membuat random data dari dua inputan yang di masukkan pengguna. inputan data pengguna akan diperoleh dari argumen yang diinputkan pengguna os.Args
saat program di jalankan.
Selanjutnya untuk mengirimkan data antar goroutine kita menggunakan 2 channel (channelA
dan channelB
). Dengan fungsi yang kita gunakan sebagai goroutine yaitu buatRandomData()
dan cekDataDuplikat()
, sedangkan fungsi tampilData()
digunakan untuk menunggu data dari channel diterima semua.
//fungsi utama
func main() {
//cek input pengguna
if len(os.Args) != 3 {
fmt.Println("Masukkan dua integer")
os.Exit(1)
}
argumen1, _ := strconv.Atoi(os.Args[1])
argumen2, _ := strconv.Atoi(os.Args[2])
if argumen1 > argumen2 {
fmt.Printf("Nilai %d harus lebih kecil dari %d",
argumen1, argumen2)
return
}
rand.Seed(time.Now().UnixNano())
channelA := make(chan int)
channelB := make(chan int)
go buatRandomData(argumen1, argumen2, channelA)
go cekDataDuplikat(channelA, channelB)
tampilData(channelB)
}
Fungsi buat random data
Fungsi pertama yang akan kita gunakan sebagai goroutine memerlukan tiga argumen, argumen min
dan max
dari inputan pengguna program dan channel output
dimana digunakan untuk menulis atau mengirim data.
Seperti yang bisa kita lihat channel output
digunakan hanya untuk menulis data dimana simbol panahnya berada di sebelah kanan keyword chan (output chan<- int
).
Didalam fungsi ini kita hanya membuat random angka di dalam perulangan yang tak terhingga, Jadi fungsi ini akan terus menulis random data selama kondisi channel tidak ditutup if TutupChannelA == true
. Jika kondisinya terpenuhi maka channel output akan di tutup dan keluar dari perulangan.
// menulis random data ke channel
func buatRandomData(min, max int, output chan<- int) {
for {
if TutupChannelA == true {
close(output)
return
}
output <- rand.Intn(max-min) + min
}
}
Fungsi untuk Mengecek data duplikat
Fungsi goroutine kedua kita dan goroutine terakhir yaitu cekDataDuplikat()
menggunakan dua arah channel sebagai argumennya. channel pertama input <-chan int
untuk dibaca atau diterima datanya dan channel kedua output chan<- int
untuk menulis data atau mengirim data keluar dari fungsi.
Dari dua argumen tersebut kita bisa membedakan mana yang untuk mengirim dan menerima data, kita tidak bisa menggunakan channel input <-chan int
untuk mengirim data dan sebaliknya juga pada channel output chan<- int
.
Dalam fungsi ini kita mengecek apakah datanya sudah ada menggunakan data map dimana kita menggunakan nilai data dari channel untuk digunakan sebagai kunci DATA[value]
data map tidak membolehkan ada kunci yang sama, jadi kita bisa memanfaatkan fitur ini.
Untuk perulangannya akan keluar sendiri ketika sudah tidak ada data yang diterima atau channel utama tidak lagi mengirimkan data (channel sudah ditutup). Jika channel utama ditutup maka channel output
juga perlu ditutup, karena tidak ada data lagi yang perlu dikirim.
// cek data duplikat, membaca dan menulis data ke channel
func cekDataDuplikat(input <-chan int, output chan<- int) {
for value := range input {
_, sudahAda := DATA[value]
if sudahAda == true {
TutupChannelA = true
} else {
DATA[value] = true
output <- value
}
}
close(output)
}
Menampilkan data dan menjumlahkan nilai
Untuk fungsi menampilkan datanya akan dieksekusi langsung di fungsi utama program. Jadi kita akan menggunakan fungsi ini untuk menunggu sampai semua data dari channel diterima semua atau bisa diartikan bahwa semua fungsi goroutine selesai dengan tugasnya.
Fungsi tampil data hanya menerima data dari channel input <-chan int
kemudian menampikan datanya ke console terminal. Penjumlahan nilainya hanya sebagai tambahan, kamu bisa menhapusnya, tapi disini kita akan menggunakannya untuk informasi tambahan di console.
// membaca data dari channel dan menjumlahkan nilainya
func tampilData(input <-chan int) {
jumlah := 0
for value := range input {
fmt.Print(value, " ")
jumlah = jumlah + value
}
fmt.Println("\nJumlah nilai data adalah", jumlah)
}
Menjalankan dan Hasil output program.
Untuk menjalankan program kita perlu menambahkan argumen seperti contoh go run main.go 2 9
dimana 2
dan 9
adalah argumen yang kita berikan pada program.
Dan disini kita bisa melihat bahwa program kita menjalankan semua goroutine dengan konstan menunggu semua goroutine selesai dan menampilkan output. Kita tidak tau urutan datanya karena datanya random tapi kita bisa melihat hasilnya semua di kumpulkan dengan sempurna.
> $ go run main.go 2 9
7 4 8 3 6
Jumlah nilai data adalah 28