Go:channel
一、channel
基本使用
package main import (
"fmt"
) func main() {
// 使用 make 创建 channel
// 方式1
var intChan chan int
intChan = make(chan int, 3)
// 方式2
// intChan := make(chan int, 3) fmt.Printf("aChan的值:%v\n", intChan) // 0xc000086000
fmt.Printf("aChan本身的地址:%p\n", &intChan) // 0xc000080018 // 向管道发送值(注意给channel放入数据时,不能超过其容量)
intChan <- 10
intChan <- 20
fmt.Printf("aChan的len:%v\n", len(intChan)) //
fmt.Printf("aChan的cap:%v\n", cap(intChan)) // // 从管道中读取数据
int1 := <- intChan
int2 := <- intChan
fmt.Println(int1, int2) // 10 20
}
示例1
package main import (
"fmt"
) type Cat struct {
Name string
Age int
} func main() {
// 定义一个存放任意数据类型的管道3个数据
allChan := make(chan interface{}, 3)
allChan <- 10
allChan <- "pd"
cat := Cat{"tom", 10}
allChan <- cat
// 如果希望获得到管道中的第三个元素,则需先将前2个推出
<- allChan
<- allChan
newCat := <- allChan
fmt.Printf("newCat=%T , newCat=%v\n", newCat, newCat)
// fmt.Println(newCat.Name) // 编译不通过,错误
fmt.Println(newCat.(Cat).Name) // 使用类型断言,正确
}
示例2
channel 使用注意事项:
- channel中只能存放指定的数据类型;
- channel的数据放满后,就不能在放入了;
- 如果从 channel 取出数据后,就可以继续放入了;
- 在没有使用 goroutine 的情况下,如果 channel 数据被取完了,再取,就会报 dead lock。
二、关闭 channel
func main() {
intChan := make(chan int, 3)
intChan <- 10
intChan <- 20
// 关闭 channel
close(intChan)
// 关闭 channel 后,无法将数据写入到 channel 中,读取数据是可以的
num := <- intChan
fmt.Println(num) // 10
}
三、遍历 channel
channel 支持 for-range 的方式进行遍历:
- 在遍历时,如果 channel 没有关闭,则会出现 deadlock 错误;
- 在遍历时,如果 channel 已经关闭,则会正常遍历数据,遍历完后,就会退出遍历。
package main
import "fmt"
func main() {
ch := make(chan int, 3)
ch <- 10
ch <- 20
ch <- 30
// 关闭 channel
close(ch)
// 遍历 channel
for v := range ch {
fmt.Println(v)
}
}
四、应用实例
实例1:
- 开启一个 writeData 协程,向管道中写入30个整数;
- 开启一个 readData 协程,从管道中读取writeData写入的数据;
- writeData 和 readData 操作的是同一个管道;
- 主线程需要等待这两个协程都完成工作才能退出。
package main import "fmt" // 将数据放入管道
func writeData(intChan chan int) {
for i := 1; i <= 30; i++ {
// 放入数据
intChan<- i
fmt.Printf("写入数据:%v\n", i)
}
close(intChan) // 关闭管道
} // 从管道中获取数据
func readData(intChan chan int, exitFlagChan chan bool) {
for {
v, ok := <-intChan
if !ok {
break
}
fmt.Printf("获取数据:%v\n", v)
}
// 读取完数据后,写入一个"标志"到另一个管道
exitFlagChan<- true
close(exitFlagChan) // 关闭管道
} func main() {
intChan := make(chan int, 10)
exitFlagChan := make(chan bool, 1)
go writeData(intChan)
go readData(intChan, exitFlagChan)
// 获取"标志",用于结束主线程
for {
_, ok := <-exitFlagChan
if !ok {
break
}
}
}
阻塞:

对于示例1中,如果注销掉上图中的这行代码(即相当于只是向管道写入数据,而没有获取数据)。就会出现阻塞而发生 deadlock,原因是 intChan 的容量是10,而写入数据确是 50 个。
如果,编译器运行时发现一个管道只有写,没有读,则该管道会阻塞。PS:写管道和读管道的速度(频率)不一致,是没有关系的。
实例2:
需求:统计 1-5000 的数字中,那些是素数?
分析:
- 传统的方式:使用一个循环,判断各个数是不是素数;
- 协程的方式:将统计的素数的任务分配给(4个)goroutine 去完成(完成任务时间短)。
package main import "fmt" // 向intChan放入1-5000个整数
func putNum(intChan chan int) {
for i := 1; i <= 5000; i++ {
intChan<- i
}
close(intChan)
} // 从intChan取出数据,并判断是否为素数,如果是,就放入到resultChan中
func getNum(intChan chan int, resultChan chan int, exitChan chan bool) {
var flag bool
for {
num, ok := <-intChan
if !ok {
// intChan 取不到
break
}
// flag默认为true(假设取到的是素数)
flag = true
// 判断num是不是素数
for i := 2; i < num; i++ {
if num % i == 0 { // 说明该num不是素数
flag = false
break
}
}
if flag {
// 将这个数就放入到resultChan
resultChan<- num
}
}
// 还不能关闭 resultChan,因为是4个协程在工作
// 向 exitChan 写入true
exitChan<- true
} func main() {
// 保存原始数据的管道
intChan := make(chan int , 500)
// 保存结果的管道
resultChan := make(chan int, 1000)
// 标识退出的管道
exitChan := make(chan bool, 4) // 4个
// 产生数据
go putNum(intChan)
// 开启4个协程,从intChan取出数据,并判断是否为素数,如果是,就放入到resultChan
for i := 0; i < 4; i++ {
go getNum(intChan, resultChan, exitChan)
}
// 主线程进行处理,当从resultChan取出了4个结果,就可以放心的关闭resultChan
go func(){
for i := 0; i < 4; i++ {
<-exitChan
}
close(resultChan)
}()
// 遍历resultChan,把结果取出
count := 0
for {
r, ok := <-resultChan
if !ok{
break
}
count += 1
fmt.Printf("素数:%d\n", r)
}
fmt.Printf("素数数量:%d\n", count)
fmt.Println("主线程退出")
}
Go:channel的更多相关文章
- Go基础系列:channel入门
Go channel系列: channel入门 为select设置超时时间 nil channel用法示例 双层channel用法示例 指定goroutine的执行顺序 channel基础 chann ...
- Java NIO学习系列二:Channel
上文总结了Java NIO中的Buffer相关知识点,本文中我们来总结一下它的好兄弟:Channel.上文有说到,Java NIO中的Buffer一般和Channel配对使用,NIO中的所有IO都起始 ...
- handy源码阅读(四):Channel类
通道,封装了可以进行epoll的一个fd. struct Channel: private noncopyable { Channel(EventBase* base, int fd, int eve ...
- Netty入门(二):Channel
前言 Netty系列索引: 1.Netty入门(一):ByteBuf 2.Netty入门(二):Channel 在Netty框架中,Channel是其中之一的核心概念,是Netty网络通信的主体,由它 ...
- go:channel(未完)
注:1)以下的所有讨论建立在包含整形元素的通道类型之上,即 chan int 2)对于“<-”我的理解是,它可能是一个操作符(接收操作符),也 可能是类型的一部分(如“chan<- in ...
- GO语言练习:channel 缓冲机制
1.代码 2.运行 3.解析 1.代码 buffer.go package main import ( "fmt" "time" ) func readThre ...
- 专题:Channel Bonding/bonding
EtherChannel最初是由cisco提出,通过聚合多条物理链路为单条逻辑链路,从而实现高可用及提高吞吐量等目的.AgP(Port Aggregation Protocol,Cisco专有协议). ...
- (转)[疯狂Java]NIO:Channel的map映射
原文出自:http://blog.csdn.net/lirx_tech/article/details/51396268 1. 通道映射技术: 1) 其实就是一种快速读写技术,它将通道所连接的数据节点 ...
- Java-NIO(六):Channel聚集(gather)写入与分散(scatter)读取
Channel聚集(gather)写入: 聚集写入( Gathering Writes)是指将多个 Buffer 中的数据“聚集”到 Channel. 特别注意:按照缓冲区的顺序,写入 positio ...
随机推荐
- 关于国债的一些计算: 理论TF价格2(缴款日前有付息)
计算 ExpectedTFPrice 是一个比较复杂的计算,我们这里讨论复杂的一种情况. 给定一只可交割国债bond(一般为CTD),一个国债期货tf, 在t日(表示tf的一个交易日期,我们通过bon ...
- Photoshop下载
Adobe Photoshop,简称“PS”,是由Adobe Systems开发和发行的图像处理软件.Photoshop主要处理以像素所构成的数字图像.使用其众多的编修与绘图工具,可以有效地进行图片编 ...
- ultraedit 窗口布局
回复默认的设置:工具栏中的视图-->环境-->左边小框里选择“编程员”,再点选择环境 改变使UltraEdit有多个窗口出来 视图’——‘视图/列表’——‘打开文件标签
- nginx媒体类型
在服务器的响应头中,有Content-Type一行,表明传输的http媒体类型. 比如:txt文件就用text/plain 表明. conf/mime.type types { text/html h ...
- JAVA学习笔记(一)配置环境
java语言的两种机制: Java 的虚拟机机制(JVM):虚拟机机制保证Java程序的跨平台特性. Java 的垃圾回收机制:垃圾回收机制保证Java程序更安全.更高效. 环境搭配:安装JDK和JR ...
- Codeforces Round #322 (Div. 2)
水 A - Vasya the Hipster /************************************************ * Author :Running_Time * C ...
- Web service简介 与servletContext的参数
Web service顾名思义是基于web的服务,它是一种跨平台,跨语言的服务. 我们可以这样理解它,比如说我们可以调用互联网上查询天气信息的web服务,把它嵌入到我们的B/S程序中,当用户从我们的网 ...
- oracle 数据导入、导出
导入导出 --数据导出备份和导入 ------注意 导出和导入 必须是CMD 命令行下操作,而不是SQL编辑器中 --1.导出表 . --exp:导出关键字 ,userid:用户权限 ,file:保存 ...
- 在Android上使用酷狗歌词API
参考自http://blog.csdn.net/u010752082/article/details/50810190 代码先贴出来: public void searchLyric(){ final ...
- 洛谷 U10206 Cx的治疗
题目背景 「Cx的故事」众所周知,Cx是一个宇宙大犇.由于Cx在空中花园失足摔下,导致他那蕴含着无穷智慧的大脑受到了严重的损伤,许多的脑神经断裂.于是,Cx的wife(有么?)决定请巴比伦最好的医师治 ...