← Danh sách bài học
Bài 17/20
📡 Bài 17: Channel
🎯 Mục tiêu:
- Hiểu Channel là gì
- Gửi và nhận dữ liệu qua channel
- Buffered vs Unbuffered channels
- Select statement
1. Channel Là Gì?
Channel là "ống dẫn" để goroutines giao tiếp và đồng bộ với nhau.
package main
import "fmt"
func main() {
// Tạo channel kiểu string
ch := make(chan string)
// Goroutine gửi data
go func() {
ch <- "Hello!" // Gửi vào channel
}()
// Main nhận data
msg := <-ch // Nhận từ channel
fmt.Println(msg) // Hello!
}
💡 Cú pháp:
•
•
•
ch <- value - gửi value vào channel•
value := <-ch - nhận value từ channel
2. Unbuffered Channel
Channel mặc định là unbuffered - gửi sẽ block cho đến khi có goroutine nhận.
func main() {
ch := make(chan int) // Unbuffered
go func() {
ch <- 42 // Block đến khi có người nhận
}()
value := <-ch // Nhận và unblock sender
fmt.Println(value)
}
3. Buffered Channel
Có thể gửi mà không cần chờ nhận ngay (đến khi buffer đầy).
func main() {
ch := make(chan int, 3) // Buffer size = 3
ch <- 1
ch <- 2
ch <- 3
// ch <- 4 // Sẽ block vì buffer đầy!
fmt.Println(<-ch) // 1
fmt.Println(<-ch) // 2
fmt.Println(<-ch) // 3
}
4. Range và Close
func main() {
ch := make(chan int)
go func() {
for i := 1; i <= 5; i++ {
ch <- i
}
close(ch) // Đóng channel khi xong
}()
// Range tự dừng khi channel closed
for num := range ch {
fmt.Println(num)
}
}
⚠️ Lưu ý: Chỉ sender đóng channel. Gửi vào channel đã đóng sẽ panic!
5. Select Statement
Select cho phép chờ nhiều channels cùng lúc.
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() { ch1 <- "từ channel 1" }()
go func() { ch2 <- "từ channel 2" }()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
}
}
}
6. Timeout Với Select
import "time"
func main() {
ch := make(chan string)
go func() {
time.Sleep(2 * time.Second)
ch <- "kết quả"
}()
select {
case result := <-ch:
fmt.Println(result)
case <-time.After(1 * time.Second):
fmt.Println("Timeout!")
}
}
📝 Tóm Tắt
make(chan T)- unbuffered channelmake(chan T, n)- buffered channelch <- vgửi,<-chnhậnclose(ch)đóng channelselectchờ nhiều channels