This is a creation in Article, where the information may have evolved or changed. Sometimes there is a scenario where you wait for multiple events to arrive, and then return as many events as possible, and block the wait if no events arrive. For example, the server waits for a client to establish a connection, or waits for client data to have such an application requirement. In the go language, you can use the Select primitive and its non-blocking (default) branch combination to achieve this functionality:
// 从ch获取尽可能多的数据放到events里,并返回实际数量;如果没有数据就阻塞等待func wait(ch chan int, events []int) int { count := 0 for count < len(events) { select { case x := <-ch: events[count] = x count++ default: if count > 0 { return count } events[count] = <-ch count++ } } return count}
If Plus exit check:
import "errors"func wait(ch chan int, exit chan bool, events []int) (int, error) { count := 0 for count < len(events) { select { case <-exit: return 0, errors.New("exit") case x := <-ch: events[count] = x count++ default: if count > 0 { return count, nil } select { case <-exit: return 0, errors.New("exit") case x := <-ch: events[count] = x count++ } } } return count, nil}
As you can see, the implementation here has a lot of repetitive code, which is very lengthy and difficult to read. We can use the channel following features to rewrite: 1. Permanent blocking when reading or writing to an empty channel 2. Reads an already closed channel immediately returns a null value
import "errors"var (CLOSED = make(chan int))func init() {close(CLOSED)}func pass(flag bool) chan int {if flag {return CLOSED}return nil}func wait(ch chan int, exit chan bool, events []int) (int, error) {count := 0LOOP:for count < len(events) {select {case <-exit:return 0, errors.New("exit")case x := <-ch:events[count] = xcount++case <-pass(count > 0):break LOOP}}return count, nil}
Now the implementation is relatively clear and concise and easy to read.