Channel Ber-buffer vs Tanpa Buffer
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 61 dari 107.
Channel yang kita gunakan sejauh ini bersifat tanpa buffer. Channel tersebut tidak memiliki kapasitas untuk menyimpan nilai. Operasi pengiriman akan memblokir hingga goroutine lain menerima, begitu pula sebaliknya. Channel dengan buffer menambahkan penyimpanan internal sehingga pengiriman dapat selesai tanpa penerima langsung.
Buat channel ber-buffer dengan memberikan kapasitas ke make:
// Tanpa buffer, kapasitas 0
unbuffered := make(chan int)
// Dengan buffer, kapasitas 3
buffered := make(chan int, 3)Pada channel dengan buffer, pengiriman hanya akan terhenti saat buffer penuh, dan penerimaan hanya akan terhenti saat buffer kosong:
ch := make(chan string, 2)
ch <- "first" // tidak tertahan, buffer masih punya ruang
ch <- "second" // tidak tertahan, buffer masih punya ruang
// ch <- "third" akan tertahan, buffer sudah penuh
fmt.Println(<-ch) // "first"
fmt.Println(<-ch) // "second"Gunakan len(ch) untuk memeriksa jumlah item yang saat ini ada di buffer, dan cap(ch) untuk kapasitas totalnya.
Kapan menggunakan masing-masing: Channel tanpa buffer menyediakan sinkronisasi yang ketat: pengirim tahu bahwa penerima telah mendapatkan nilai tersebut. Channel dengan buffer memisahkan waktu pengirim dan penerima, berguna saat produsen dan konsumen bekerja dengan kecepatan yang berbeda. Namun, channel dengan buffer dapat menyamarkan bug sinkronisasi, jadi utamakan channel tanpa buffer kecuali kamu punya alasan khusus untuk menggunakan buffer.
Tantangan
MudahMari buat pemroses batch yang menunjukkan perbedaan antara channel berbuffer dan tanpa buffer. Kamu akan membuat sistem tempat producer mengirim item ke pemroses, menggunakan channel berbuffer untuk memisahkan waktu kerja keduanya dan memungkinkan producer bekerja lebih dulu.
Kamu akan mengatur kodemu dalam dua file:
processor.go: Definisikan logika pemrosesan batch menggunakan channel.Buat struct
Itemdengan fieldID(int) danValue(string).Buat dua fungsi:
Producer(items []Item, out chan Item)- Mengirim setiap item ke channel output. Setelah mengirim setiap item, cetak:Produced item [ID]. Setelah semua item dikirim, cetak jumlah item yang sedang menunggu di buffer menggunakanlen(out)dengan format:Buffer has [count] items. Lalu tutup channel.Consumer(in chan Item) []string- Menerima item dari channel input dan mengumpulkannya ke dalam slice berisi string yang telah diformat. Untuk setiap item yang diterima, string-nya harus berupa:Consumed: [ID] - [Value]. Kembalikan slice saat channel ditutup.
main.go: Siapkan channel berbuffer dan koordinasikan producer dan consumer.Baca kapasitas buffer, lalu jumlah item, diikuti ID dan nilai setiap item. Buat channel berbuffer dengan kapasitas yang ditentukan. Jalankan Producer terlebih dahulu (bukan sebagai goroutine) untuk mengisi buffer, lalu jalankan Consumer untuk memproses semua item. Cetak setiap hasil yang dikonsumsi pada baris terpisah.
Input berikut akan diberikan:
- Baris 1: Kapasitas buffer (integer)
- Baris 2: Jumlah item (integer)
- Baris berikutnya: Untuk setiap item, dua baris, yaitu ID item (integer), lalu nilainya (string)
Contohnya, jika diberikan:
3
3
1
apple
2
banana
3
cherryOutput-mu harus berupa:
Produced item 1
Produced item 2
Produced item 3
Buffer has 3 items
Consumed: 1 - apple
Consumed: 2 - banana
Consumed: 3 - cherryPerhatikan bahwa dengan kapasitas buffer 3, producer dapat mengirim semua 3 item tanpa terblokir, dan buffer menampilkan 3 item yang menunggu sebelum consumer mulai bekerja. Jika ukuran buffer lebih kecil daripada jumlah item, producer akan terblokir sambil menunggu ruang.
Coba sendiri
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Baca kapasitas buffer
line, _ := reader.ReadString('\n')
bufferCapacity, _ := strconv.Atoi(strings.TrimSpace(line))
// Baca jumlah item
line, _ = reader.ReadString('\n')
numItems, _ := strconv.Atoi(strings.TrimSpace(line))
// Baca ID dan nilai setiap item
items := make([]Item, numItems)
for i := 0; i < numItems; i++ {
line, _ = reader.ReadString('\n')
id, _ := strconv.Atoi(strings.TrimSpace(line))
line, _ = reader.ReadString('\n')
value := strings.TrimSpace(line)
items[i] = Item{ID: id, Value: value}
}
// TODO: Buat channel ber-buffer dengan kapasitas yang ditentukan
// TODO: Jalankan Producer (bukan sebagai goroutine) untuk mengisi buffer
// TODO: Jalankan Consumer untuk memproses semua item
// TODO: Cetak setiap hasil yang dikonsumsi pada baris terpisah
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online