Channel概念

Channel 是Go中的一个核心类型,你可以把它看成一个管道Channel是引用类型,操作符是箭头 <- 

Channel 是 CSP 模式的具体实现,用于多个 goroutine 通讯。其内部实现了同步,确保并发安全。

Channel 是线程安全的先进先出,多个goroutine同时访问,不需要加锁,channel是有类型的,一个整数的channel只能存放整数。

Channel定义

第一种,channel声明

声明int类型的chan

var ch chan int

声明string类型的chan

var ch chan string

声明map类型chan

var ch chan map[int]string

第二种,使用make定义,无缓冲channel

var ch1 chan int = make(chan int)
var ch2 = make(chan int)
ch3 := make(chan int)

第三种,使用make定义,有缓冲channel

var ch1 chan int = make(chan int, )
var ch2 = make(chan int, )
ch3 := make(chan int, )

第四种,只读channel

var ch1 <-chan int
var ch2 <-chan int = make(<-chan int, )
var ch3 = make(<-chan int, )
ch4 := make(<-chan int, )

第五种,只写channel

var ch1 chan<- int
var ch2 chan<- int = make(chan<- int, )
var ch3 = make(chan<- int, )
ch4 := make(chan<- int, )

Channel特点

无缓冲的与有缓冲channel有着重大差别,那就是一个是同步的 一个是非同步的。

比如

无缓冲chan:ch1:=make(chan int)

有缓冲chan:ch2:=make(chan int,1)

无缓冲: ch1<-1 不仅仅是向 c1 通道放 1,而是一直要等有别的携程 <-ch1 接手了这个参数,那么ch1<-1才会继续下去,要不然就一直阻塞着。

有缓冲: ch2<-1 则不会阻塞,因为缓冲大小是1(其实是缓冲大小为0),只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。

缓冲区是内部属性,并非类型构成要素。

普通 channel 可以隐式转为只读channel或只写channel。

package main

var ch = make(chan int, )
var send chan<- int = ch
var recv <-chan int = ch func main() { }

只读channel或只写channel不能转为普通 channel。

package main

func main() {
var send chan<- int
var recv <-chan int ch1 := (chan int)(send)
ch2 := (chan int)(recv)
}

编译错误:

./main.go::: cannot convert send (type chan<- int) to type chan int
./main.go::: cannot convert recv (type <-chan int) to type chan int

Channel操作

使用内置函数 len() 返回未被读取的缓冲元素数量,使用内置函数 cap() 返回缓冲区大小。

package main

import "fmt"

func main() {
ch1 := make(chan int)
ch2 := make(chan int, ) ch2 <- fmt.Printf("ch1 缓冲元素数量:%v,缓冲区大小:%v\n", len(ch1), cap(ch1))
fmt.Printf("ch2 缓冲元素数量:%v,缓冲区大小:%v\n", len(ch2), cap(ch2))
}

运行结果:

ch1 缓冲元素数量:,缓冲区大小:
ch2 缓冲元素数量:,缓冲区大小:

channel 写入、读取操作:

package main

import "fmt"

func main() {
ch := make(chan int, )
// 写入chan
ch <- // 读取chan
value, ok := <-ch
if ok {
fmt.Printf("读取chan:%v\n", value)
} }

channel 关闭操作

1、使用内置函数 close() 进行关闭 chan。
2、chan关闭之后,for range遍历chan中已经存在的元素后结束。
3、没有使用for range的写法需要使用,val, ok := <- ch进行判断chan是否关闭。

package main

import "fmt"

func main() {
ch := make(chan int, ) ch <-
ch <-
ch <- close(ch)
for {
val, ok := <-ch
if ok == false {
fmt.Println("chan is closed")
break
}
fmt.Println(val)
}

注意:向已经关闭的 channel 发送数据会引发 panic 错误。

package main

func main() {
ch := make(chan int, )
close(ch)
ch <-
}

运行错误:

panic: send on closed channel

最新文章

  1. jQuery- 表单验证插件-Validation
  2. jQuery常用方法验证
  3. bootstrap如何给.list-group加上序号
  4. jedisPool.returnBrokenResource 弃用
  5. serialization机制
  6. YTU 2614: A代码完善--系统日期
  7. 获取SqlDataReader的列名
  8. C#日期转换类
  9. ubuntu下配置qt+opengl+opencv
  10. .net下灰度模式图像
  11. 自己写的python脚本(抄的别人的,自己改了改,用于整理大量txt数据并插入到数据库)
  12. php的empty()和isset()用法
  13. 项目启动时候spring是如何加载和实例化各类的
  14. SQL Server 服务器主体拥有一个或多个端点无法删除;错误15141
  15. 爬虫须知的HTTP协议
  16. Netty 5 io.netty.util.IllegalReferenceCountException 异常
  17. faster rcnn源码阅读笔记3
  18. 【Java】【4】关于Java中的自增自减
  19. Elasticsearch分布式机制探究
  20. prisma 服务器端订阅试用

热门文章

  1. Ubuntu在命令行下将默认语言改为英语
  2. iPhone X 的“刘海”正是苹果的品牌象征
  3. [转]如何创建一个自签名的SSL证书(X509)
  4. Mac Sublime Text 浏览器 设置快捷键 让html文件在浏览器打开
  5. underscore概况
  6. Java动态代理(二)CGLIB动态代理应用
  7. Android-Java读写文件到自身APP目录
  8. asp.net——Base64加密解密
  9. Python学习之全局变量与global
  10. RoadFlowCore工作流引擎快速入门