[go]channel和select

onequid · · 930 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

channel

channel用于协程(goroutine)间的通信,对channel进行发送(send)或接收(receive)操作可能会阻塞当前协程。

用make创建一个channel

可以用make(chan Type, BufferSize)来创建一个新的channel,Type表示channel中元素的类型,BufferSize(可选)为缓冲区大小,缓冲区过大溢出会处理成无缓冲区。

c := make(chan int)
//c := make(chan int, 0) 与上面相等,没有缓冲区

缓冲区

  • channel有缓冲区,且缓冲区没有被填满的时候,发送操作不会阻塞goroutine,
  • 反之没有缓冲区或缓冲区被填满的channel,发送操作会阻塞goroutine。

单向channel:ReceiverOnly, SenderOnly

在声明方法时,可以将channel定义为单向的ReceiverOnly或SenderOnly,ReceiverOnly只能接受不能发送,相反地,SenderOnly只能发送不能接受。

也可以在用make创建单向channel,因为单向channel不能转换为双向channel,没有什么实用意义。

//chrcvr 是单向的ReceiverOnly channel
func recieve(chrcvr <-chan int){
    e := <- chrcvr // `chrcvr <- 1`报错,不能编译
    //...
}

// chsndr 是单向的SenderOnly channel
func send(chsndr chan<- int) {
    send <- 3 //`<- send` 报错,不能编译
}
c := make(chan int)

go func(rcvr <-chan int) {
    println(<-rcvr)
}(c)

c <- 1

close(channel)

The close built-in function closes a channel, which must be either bidirectional or send-only. It should be executed only by the sender, never the receiver, and has the effect of shutting down the channel after the last sent value is received. After the last value has been received from a closed channel c, any receive from c will succeed without blocking, returning the zero value for the channel element. The form
x, ok := <-c
will also set ok to false for a closed channel.

close(c chan<-Type)方法关闭一个双向或发送方channel。应该由发送方而不是接收方执行这个方法,并会在最后一个被发送的值被接收后关闭该channel。在关闭的channel的最后一个值被接收后,任何接收都会无阻碍地成功地返回channel元素的零值。对关闭的通道使用x,ok := <-c格式,也会把ok赋值为false

类型

这篇文章提到channel是值拷贝的。

select

select会从可能的发送(send)或接受(receive)操作集合中选择一个执行,它的语法与switch相似。

select {
    case i := <-c1:
        println(i)
    case c2 <- 123:
        //...
    default:
        //...
}
  • 如果集合中的操作都不能执行,阻塞直到其中一个可以执行;
  • 如果集合中有一个或多个操作可以执行,随机执行一个;

nil的channel会阻塞协程,如果select中只有nil的channel,或者select没有选项select{},select也会阻塞协程。
default使select不会阻塞:

  • 如果除了default之外的操作可以执行,执行其中一个;
  • 如果其他操作都不能执行,执行default。

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:onequid

查看原文:[go]channel和select

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

930 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传