iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
自我挑戰組

Concurrency in go 讀書心得系列 第 18

18.Or-done-channel

  • 分享至 

  • xImage
  •  

有時你會與來自系統不同部分的Channel(通道)交互。與pipeline(管道)不同的是,當你使用的代碼通過done通道取消操作時,你無法對通道的行為方式做出判斷。也就是說,你不知道正在執行讀取操作的goroutine現在是什麽 狀態。出於這個原因,正如我們在“防止Goroutine泄漏”中所闡述的那樣,需要用select語句來封裝我們的讀取操作和done通道。可以簡單的寫成這樣:

loop:
for {
          select {
          case <-done:
              break loop
          case maybeVal, ok := <-myChan:
              if ok == false {
                  return // or maybe break from for
                }
              // Do something with val
          }
}

這樣做可以快速退出嵌套循環。繼續使用goroutines編寫更清晰的並發代碼,而不是過早優化的主題,我們可以用一個goroutine來解決這個問題。

我們封裝了細節,以便其他人調用更方便:

func main() {
	orDone := func(done, c <-chan interface{}) <-chan interface{} {
		valStream := make(chan interface{})
		go func() {
			defer close(valStream)
			for {
				select {
				case <-done:
					return
				case v, ok := <-c:
					if ok == false {
						return
					}
					select {
					case valStream <- v:
					case <-done:
					}
				}
			}
		}()
		return valStream
	}
	bridge := func(
		done <-chan interface{},
		chanStream <-chan <-chan interface{},
	) <-chan interface{} {
		valStream := make(chan interface{}) // <1>
		go func() {
			defer close(valStream)
			for { // <2>
				var stream <-chan interface{}
				select {
				case maybeStream, ok := <-chanStream:
					if ok == false {
						return
					}
					stream = maybeStream
				case <-done:
					return
				}
				for val := range orDone(done, stream) { // <3>
					select {
					case valStream <- val:
					case <-done:
					}
				}
			}
		}()
		return valStream
	}
	genVals := func() <-chan <-chan interface{} {
		chanStream := make(chan (<-chan interface{}))
		go func() {
			defer close(chanStream)
			for i := 0; i < 10; i++ {
				stream := make(chan interface{}, 1)
				stream <- i
				close(stream)
				chanStream <- stream
			}
		}()
		return chanStream
	}

	for v := range bridge(nil, genVals()) {
		fmt.Printf("%v ", v)
	}
}


上一篇
17.Fan in, Fan out
下一篇
19.Tee-channel
系列文
Concurrency in go 讀書心得30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言