简单得说,如果两个channel同时到达,case的消费顺序是随机的。
参考:https://studygolang.com/articles/28353?fr=sidebar
下面的代码可以保证select的时候case rs := <-ch:先执行, case <-done:最后执行,原因是make(chan *int)由于长度不够,所以它会阻塞后被消费才释放。
func TestSelect(t *testing.T) {
ch := make(chan *int)
len := 100
wg := sync.WaitGroup{}
wg.Add(len)
done := make(chan struct{})
for i := 0; i < len; i++ {
iC := i
go func() {
defer wg.Done()
// 此行代码阻塞, 由于channel长度不够的原因, 当被消费后释放
ch <- &iC
}()
}
go func() {
wg.Wait()
done <- struct{}{}
}()
time.Sleep(time.Second)
ans := make([]*int, 0)
waitLoop:
for {
fmt.Println("for ...")
select {
case <-done:
fmt.Println("done")
break waitLoop
case rs := <-ch:
fmt.Println("case", *rs)
time.Sleep(time.Millisecond * 10)
ans = append(ans, rs)
time.Sleep(time.Millisecond * 10)
}
}
for _, v := range ans {
fmt.Printf("%v ", *v)
}
}
func TestSelect2(t *testing.T) {
ch := make(chan int)
go func() {
ch <- 1
fmt.Println("<-结束")
}()
time.Sleep(time.Second * 5)
fmt.Println("5秒后")
select {
case i := <-ch:
fmt.Println("<-", i)
}
}