chan基本用法

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

## Channel Channel用于数据传递或数据共享,其本质上是一个先进先出的队列,使用Goroutine 和channel进行数据通讯简单高效,同时也线程安全,多个Goroutine可同时修改一个Channel,不需要加锁 在channel中箭头的指向是数据的流向,和map类似,channel也一个对应make创建的底层数据结构的引用 ``` ch := make(chan int) ch <- p // 发送值p到Channel ch中 p := <-ch // 从Channel ch中接收数据,并将数据赋值给p ``` 和其它的引用类型一样,channel的零值也是nil. chan类型的定义格式: `ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) Type .` <-代表channel的方向。如果没有指定方向,那么Channel就是双向的,既可以接收数据,也可以发送数据 ``` chan p //可以接受发送类型为p的数据 chan<- float64 //可以用来发送float64类型数据 <-chan int //可以用来接收int类型数据 ``` make初始化chan可以设置channel的容量,容量代表channel缓存的大小,没有缓存只有sender和receiver都准备 好了之后他们的通信才会发生。设置了缓存就可能不会发生阻塞,只有buffer满了之后send才会阻塞,之后缓存 空了之后receive才会阻塞。一个nil chan 不会通信 ### 无缓冲channels 发送和接收动作是同时发生的Channels的发送和接收操作将导致两个goroutine做一次同步操作。因为这个原因,无缓存Channels有时候也被称为同步Channels 。如果没有 goroutine 读取 channel (<- channel),则发送者 (channel <-) 会一直阻塞。 ### 缓冲的Channels 缓冲:缓冲 channel 类似一个有容量的队列。当队列满的时候发送者会阻塞;当队列空的时候接收者会阻塞。 使用channel之后可以进行关闭,关闭channel后,对该channel的任何发送操作都将导致panic异常。对一个已经被close过的channel之行接收操作依然可以接受到之前已经成功发送的数据;如果channel中已经没有数据的话讲产生一个零值的数据。 关闭chan close(ch) - 重复关闭 channel 会导致 panic. - 向关闭的 channel 发送数据会 panic. - 从关闭的 channel 读数据不会 panic,读出channel中已有的数据之后再读就是channel类似的默认值 判断默认值胡子和关闭ok语法 ``` ch := make(chan int, 10) ... close(ch) val, ok := <-ch if ok == false { //channel closed } ``` ### chan的经典用法 1. goroutine使用chan通信 ``` func main(){ x := make(chan int) go func(){ x <- 1 }() <- x } ``` 2. select选择一组可能的send receive操作去处理 ``` select { case e, ok := <-ch1: //TODO case e, ok := <-ch2: //TODO default: } for { select { //TODO } } ``` 3. range channel ``` 使用range channel 我们可以直接取到 channel 中的值。当我们使用 range 来操作 channel 的时候,一旦 channel 关闭,channel 内部数据读完之后循环自动结束。 func consumer(ch chan int){ for x := range ch{ fmt.Println(x) } } func producer(ch chan int) { for _,v range values { ch <-v } } ``` 4. 超时控制 ``` select如果没有case需要处理,就会一直阻塞, select可以实现超时控制 func main(){ chstr := make(chan string, 1) go func(){ time.Sleep(time.Second * 2) chstr <- "retuslt" }() select{ case res := <-chstr: fmt.Println(res) case <- time.After(time.Second * 1): fmt.Println("timeout") } } ``` 5. chan同步 channel 将goroutine 隔离开,并发编程的时候可以将注意力放在 channel 上 ``` func mission(done chan bool){ time.Sleep(time.Second) //通知任务完成 done <- true } func main(){ done := make(chan bool, 1) go mission(done) //等待mission任务完成 <-done } ```

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

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

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