• 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)
    		}
    	}
    }
    
  • 相关阅读:
    分母为0一定会抛异常吗?
    [译]Zookeeper的优点与局限性
    明明有class为什么还是报ClassNotFoundException?
    广告倒排索引架构与优化
    KafkaProducer源码分析
    Kafka服务端之网络连接源码分析
    Sublime常用快捷键
    sublime主题设置
    Sublime前端插件
    安装软件,更新软件,删除软件
  • 原文地址:https://www.cnblogs.com/f-ck-need-u/p/9994508.html
Copyright © 2020-2023  润新知