select không có default sẽ chặn cho tới khi một nhánh sẵn sàng. Thêm default biến nó thành thao tác không chặn: nếu không có nhánh nào sẵn sàng ngay, default chạy luôn.
Ứng dụng chính là try-send / try-receive — bỏ bớt việc khi hệ thống quá tải thay vì để người gọi phải chờ:
go
select {
case metrics <- sample:
// enqueued
default:
dropped.Add(1) // buffer full: drop instead of blocking the caller
}Bẫy hay gặp: đặt select { case ...; default: } bên trong vòng for mà không có gì chặn lại.
Lúc đó goroutine quay vòng liên tục, ăn hết một nhân CPU trong khi chẳng làm gì.
go
for {
select {
case v := <-ch:
handle(v)
default:
// busy loop: burns a CPU core
}
}Muốn chờ mà vẫn có lối thoát thì bỏ default và thêm một nhánh thoát (<-ctx.Done(), <-time.After(...)).
Lưu ý thêm: khi nhiều nhánh cùng sẵn sàng, select chọn ngẫu nhiên đều một nhánh, không theo thứ tự viết — không được dựa vào thứ tự để làm ưu tiên.