Channel Berbuffer
Kapasitas, penutupan channel, dan range pada channel
Channel Berbuffer adalah pelajaran Go Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Go Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Go Academy mencakup 4 pelajaran total.
Apa Itu Saluran Berpenyangga?
saluran berpenyangga memiliki kapasitas — pengiriman tidak terblokir selama penyangga masih memiliki ruang. Saluran bertindak seperti antrean:
package main
import "fmt"
func main() {
ch := make(chan int, 3) // capacity 3
ch <- 1 // does not block — buffer has room
ch <- 2 // does not block
ch <- 3 // does not block
// ch <- 4 // would block — buffer full
fmt.Println(<-ch) // 1
fmt.Println(<-ch) // 2
fmt.Println(<-ch) // 3
}Saluran Berpenyangga sebagai Antrean
Saluran berpenyangga menerapkan antrean FIFO di antara goroutine:
package main
import ("fmt"; "sync")
func producer(ch chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
for i := 1; i <= 5; i++ {
ch <- i
fmt.Printf("produced %d\n", i)
}
}
func main() {
ch := make(chan int, 2) // buffer 2 — producer runs ahead
var wg sync.WaitGroup
wg.Add(1)
go producer(ch, &wg)
wg.Wait()
close(ch)
for v := range ch { fmt.Printf("consumed %d\n", v) }
}len() dan cap() pada Saluran
Periksa ukuran dan kapasitas saat ini dari saluran berpenyangga:
package main
import "fmt"
func main() {
ch := make(chan string, 5)
ch <- "a"
ch <- "b"
ch <- "c"
fmt.Println("cap:", cap(ch)) // 5
fmt.Println("len:", len(ch)) // 3 — items currently buffered
<-ch
fmt.Println("len:", len(ch)) // 2
}Memisahkan Producer dan Consumer
Penyangga memisahkan kecepatan producer dari consumer. Producer dapat berjalan lebih cepat sebesar ukuran penyangga sebelum terblokir:
package main
import ("fmt"; "sync"; "time")
func produce(ch chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
for i := 0; i < 5; i++ {
ch <- i
}
}
func consume(ch <-chan int, wg *sync.WaitGroup) {
defer wg.Done()
for v := range ch {
time.Sleep(10 * time.Millisecond) // slower consumer
fmt.Println("consumed:", v)
}
}
func main() {
ch := make(chan int, 3)
var wg sync.WaitGroup
wg.Add(2)
go produce(ch, &wg)
go consume(ch, &wg) // BUG: produce closes before consume sees all
// In practice, coordinate close carefully
fmt.Println("decoupled")
}Semafor dengan Saluran Berpenyangga
Saluran berpenyangga berkapasitas N dapat membatasi jumlah goroutine konkuren menjadi N — semafor sederhana:
package main
import ("fmt"; "sync"; "time")
func main() {
sem := make(chan struct{}, 3) // max 3 concurrent
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
i := i
go func() {
defer wg.Done()
sem <- struct{}{} // acquire
defer func() { <-sem }() // release
fmt.Printf("job %d running\n", i)
time.Sleep(50 * time.Millisecond)
}()
}
wg.Wait()
}Menutup Saluran Berpenyangga
Menutup saluran berpenyangga memungkinkan penerima menguras nilai yang tersisa di dalam penyangga sebelum mendeteksi penutupan:
package main
import "fmt"
func main() {
ch := make(chan int, 5)
for i := 1; i <= 3; i++ { ch <- i }
close(ch)
// Drain all buffered values after close:
for v := range ch {
fmt.Println(v) // 1, 2, 3
}
// range exits after channel closed and drained
}Berpenyangga vs Tanpa Penyangga: Kapan Memilihnya
Panduan pemilihan:
- Tanpa penyangga: serah terima sinkron yang terjamin, pengurutan ketat, sinkronisasi pertemuan
- Berpenyangga: memisahkan kecepatan producer/consumer, mengurangi pemblokiran, menerapkan semafor, mengumpulkan N hasil
- Jadikan tanpa penyangga sebagai pilihan bawaan — tambahkan penyangga hanya jika Anda dapat membenarkan ukurannya
- Ukuran penyangga yang terlalu kecil → tetap menyebabkan pemblokiran; terlalu besar → menyembunyikan bug
Mengumpulkan Hasil dengan Saluran Berpenyangga
Gunakan saluran berpenyangga untuk mengumpulkan hasil dari goroutine paralel tanpa pemblokiran:
package main
import ("fmt"; "sync")
func square(n int) int { return n * n }
func main() {
nums := []int{1, 2, 3, 4, 5}
results := make(chan int, len(nums)) // buffer = goroutine count
var wg sync.WaitGroup
for _, n := range nums {
wg.Add(1)
n := n
go func() {
defer wg.Done()
results <- square(n)
}()
}
wg.Wait()
close(results)
for r := range results { fmt.Println(r) }
}Kebocoran Goroutine dengan Penyangga Penuh
Jika penyangga penuh dan tidak ada pembaca, sender akan terblokir selamanya — menyebabkan kebocoran goroutine:
package main
import ("fmt"; "time"; "runtime")
func main() {
ch := make(chan int, 2)
// Start goroutine that fills buffer and then blocks
go func() {
ch <- 1
ch <- 2
ch <- 3 // blocks: buffer full, no receiver
fmt.Println("never reached")
}()
time.Sleep(50 * time.Millisecond)
fmt.Println("goroutines:", runtime.NumGoroutine()) // 2 — leaked
}time.After sebagai Saluran Berpenyangga
time.After mengembalikan <-chan time.Time dengan penyangga berkapasitas 1. Lingkungan eksekusi mengirim ke sana setelah durasi berlalu, lalu objek tersebut dikumpulkan oleh pengumpul sampah:
package main
import ("fmt"; "time")
func doWithTimeout(work func() string) (string, bool) {
result := make(chan string, 1)
go func() { result <- work() }()
select {
case r := <-result:
return r, true
case <-time.After(100 * time.Millisecond):
return "", false
}
}
func main() {
r, ok := doWithTimeout(func() string {
time.Sleep(50 * time.Millisecond)
return "done"
})
fmt.Println(r, ok)
}Pemeriksaan Singkat
Apa yang terjadi ketika Anda mengirim ke saluran berpenyangga yang kapasitasnya sudah penuh?
Ringkasan: Saluran Berpenyangga
Ringkasan:
make(chan T, N)membuat saluran berpenyangga dengan kapasitas N- Pengiriman terblokir hanya ketika penyangga penuh; penerimaan terblokir hanya ketika penyangga kosong
len(ch)— jumlah elemen saat ini;cap(ch)— kapasitas- Gunakan untuk memisahkan producer/consumer, mengumpulkan hasil paralel, dan menerapkan semafor
- Close memungkinkan pengurasan sebelum EOF;
range chmenanganinya secara otomatis
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Channel Berbuffer” gratis?
Ya — teks lengkap “Channel Berbuffer” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Go Academy, upgrade ke CoddyKit PRO. Kursus Go Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Channel Berbuffer”?
Kapasitas, penutupan channel, dan range pada channel Kamu berlatih Go Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Go Academy?
Tidak diperlukan pengalaman sebelumnya. Go Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Channel Berbuffer” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Go Academy ini?
Ya. Setiap pelajaran Go Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.