go语言select关注点

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

package main

import (
       "fmt"
       "time"
)

func main() {

       c1 := make(chan string)
       c2 := make(chan string)
       c3 := make(chan string)
       var c4 chan string
       c5 := make(chan string)
       close(c5)
       c6 := make(chan string, 3)
       c6 <- "buffered 1"
       c6 <- "buffered 2"
       c6 <- "buffered 3"
       close(c6)

       go func() {

              time.Sleep(time.Second * 1)
              c1 <- "one"
              close(c1)//关闭c1 channel
       }()

       go func() {

              time.Sleep(time.Second * 2)
              c2 <- "two"
       }()

       go func() {

              fmt.Println(<-c3)
       }()

       for {
              select {

              case msg1,ok := <-c1:

                     if ok {
                            fmt.Println("received1 ", msg1)
                     } else {

                            c1 = nil //判断c1 channel已经关闭后,将其赋值为nil,则此case将一直阻塞,故此select继续评估其它case,避免了死循环,
                            fmt.Println("c1 channel has closed.")
                     }
              case msg2 := <-c2: //从c2 channel中读
                     fmt.Println("received2 ", msg2)

              case c3 <- "write string": //向c3 channel中写
                     fmt.Println("c3 channel wrote.")

              case <- c4: //因为c4 is nil, 所以此case将一直阻塞,故select继续评估其它case.
                     fmt.Println("never reach here.")

              case c4 <- "never": //因为c4 is nil, 所以此case将一直阻塞,故select继续评估其它case.

                     fmt.Println("never reach here.")
              case str := <- c5: //死循环,不断地读取出零值,即空字符串。
                   fmt.Printf("empty: %s", str)
              case c5 <- "panic": //向已经关闭的channel写,发生panic异常。
                   fmt.Println("panic")
              case str := <- c6://死循环,在读取完c6中已写入的值之后,则继续不断地读取出零值,即空字符串。

                  fmt.Printf("buffered channel value: %s",str)
              case c6 <- "buffered channel closed, write to panic":
		//向已经关闭的channel写,发生panic异常。

                     fmt.Println("buffered channel closed, write to panic")
              case <- time.After(time.Second * 5): //定时器,防止操作无限期阻塞
                     fmt.Println("timeout\n")
              //default: //无default则select为阻塞等待的; 有default则为非阻塞等待的,好像spin-lock.
              //     fmt.Println("default\n")
              }
       }
}
总结: select中的每一个case 都是针对channel的IO操作,读或写,当有多个case同时就绪(可读可写)时,select会随机选择一个执行。
select{}将会永远阻塞;通常select与for并用,这样select就可以循环不断地评估每一个case,随机选取一个case执行。
其实select这个概念在linux中早就出现了, 用于监视多个文件描述符是是否有IO操作,当有文件描述符发生IO操作时,select调用立即返回,返回值中包括发生IO操作的文件描述符集合。

参考:http://tonybai.com/2014/09/29/a-channel-compendium-for-golang/
注意: 此文章只是我个人笔记, 如有错漏,请一定指正, 共同学习, 我的邮箱: htyu_0203_39@sina.com

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

本文来自:CSDN博客

感谢作者:htyu_0203_39

查看原文:go语言select关注点

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

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