Go基礎系列:nil channel用法示例


Go channel系列

當未為channel分配內存時,channel就是nil channel,例如var ch1 chan int。nil channel會永遠阻塞對該channel的讀、寫操作。

nil channel會阻塞對該channel的所有讀、寫。所以,可以將某個channel設置為nil,進行強制阻塞,對於select分支來說,就是強制禁用此分支。

以下是一個nil channel的示例:

package main

import (
	"fmt"
	"math/rand"
	"time"
)

// 不斷向channel c中發送[0,10)的隨機數
func send(c chan int) {
	for {
		c <- rand.Intn(10)
	}
}

func add(c chan int) {
	sum := 0

	// 1秒后,將向t.C通道發送時間點,使其可讀
	t := time.NewTimer(1 * time.Second)

	for {
		// 一秒內,將一直選擇第一個case
		// 一秒后,t.C可讀,將選擇第二個case
		// c變成nil channel后,兩個case分支都將一直阻塞
		select {
		case input := <-c:
			// 不斷讀取c中的隨機數據進行加總
			sum = sum + input
		case <-t.C:
			c = nil
			fmt.Println(sum)
		}
	}
}

func main() {
	c := make(chan int)
	go add(c)
	go send(c)
	// 給3秒時間讓前兩個goroutine有足夠時間運行
	time.Sleep(3 * time.Second)
}

上面的示例中,send()向通道c不斷發送10以內的隨機整數,add()則在一秒內不斷讀取通道c中的數據並進行加總。一秒時間到后,t.C通道就會有數據,第二個case分支就會被選中,第二個case會讓第一個case評估的channel變為nil channel,使得第一個case從此永久禁用,因為第二個case沒有多余的數據可讀,它也被永久禁用。總共3秒之后,main goroutine結束,程序結束。

如果不理解NewTimer(d),換成After(d)是一樣的,After(d)和NewTime(d).C是等價的。

func add(c chan int) {
	sum := 0
	t := time.After(1 * time.Second)
	for {
		select {
		case val := <-c:
			sum = sum + val
		case <-t:
			c = nil
			fmt.Println(sum)
		}
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM