github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/18channeluse/or_done_channel/main.go (about)

     1  package main
     2  
     3  import "fmt"
     4  
     5  /*
     6  这种模式是我们经常使用的一种模式, 通过一个信号channel(done)来控制(取消)输入channel的处理。
     7  一旦从done channel中读取到一个信号,或者done channel被关闭, 输入channel的处理则被取消。
     8  这个模式提供一个简便的方法,把done channel 和 输入 channel 融合成一个输出channel。
     9  
    10  就会context的前身,通过done进行取消整个运行中的任务
    11  */
    12  
    13  func orDone(done <-chan struct{}, c <-chan interface{}) <-chan interface{} {
    14  	valStream := make(chan interface{})
    15  	go func() {
    16  		defer close(valStream)
    17  		for {
    18  			select {
    19  			case <-done:
    20  				return
    21  			case v, ok := <-c:
    22  				if ok == false {
    23  					return
    24  				}
    25  				select {
    26  				case valStream <- v:
    27  				case <-done:
    28  				}
    29  			}
    30  		}
    31  	}()
    32  	return valStream
    33  }
    34  
    35  func main() {
    36  	ch := make(chan interface{})
    37  	go func() {
    38  		defer close(ch)
    39  
    40  		for i := 0; i < 10; i++ {
    41  			ch <- i
    42  		}
    43  	}()
    44  
    45  	for v := range orDone(nil, ch) {
    46  		fmt.Printf("%v ", v)
    47  	}
    48  }