golang中的channel

channel用于goroutine之间的通信

如果不用channel,使用共享全局变量的方式,需要加锁

// synchornized 同步
// golang中的 sync包中有互斥锁
var lock sync.Mutex // mutex 互斥 lock.Lock() // 上锁
// 多个goroutine同时对相同的数据进行修改
lock.Unlock() // 解锁

使用同步锁并发效率会很低

channel主要用于goroutine通信和解决主线程等待goroutine执行结束再退出的问题

basic concept of channel

  1. 本质上是一个FIFO的数据结构-队列
  2. 线程安全,不需要加锁
  3. channel是有类型的,如字符串channel chan string,只能保存string数据

declare channel

var variableName chan dataType

var c1 chan int
var c2 chan bool
var c3 chan map[int]string

channel 是引用类型,必须初始化后才能使用

var c1 chan int
c1 = make(chan int, 4) // 使用make函数初始化chan int, 4是容量
// 初识化之后容量不可动态变化,channel不会自动扩容,写入数据时不能超过容量,否则会deadlock
// fatal error: all goroutines are asleep - deadlock! c1 <- 666 // 写入数据 num := <- c1 // 取出数据, 每取一个数据,channel长度减一
// 不使用goroutine的情况下
// 当数据全部取出是再对channel取数据会报 deadlock

使用channel的注意事项

  1. 只保存指定类型数据
  2. 数据满后,不能在添加数据,否则deadlock
  3. 从channel中取出数据,长度减一,腾出一个位置可添加数据
  4. 不使用goroutine的情况下,当数据全部取出是再对channel取数据会报 deadlock

channel的遍历和关闭

内置函数close(channel) 可以关闭channel,不能再添加数据,但是可以读取数据

channel可以用for range方式遍历

但是必须是已关闭的channel

for range遍历一个未关闭的channel会出现deadlock

c1 := make(chan int, 10)
for i:=0; i<10; i++ {
c1 <- i
}
close(c1) for v := range c1 {
fmt.Println(v)
}

对于一个已关闭的channel读取数据时,如果数据已全部取出,取值状态返回false而不会报错

func main() {
c1 := make(chan int, 2)
c1 := make(chan int, 2)
c1 <- 1
c1 <- 2
c2 <- 1
c2 <- 2
close(c1)
<- c1 // 取出值 丢弃不用 1
<- c1 // 2
v, ok := <-c1 // 数据已取完
fmt.Println(v,ok) // 0 false <- c2 // 1
<- c2 // 2
v, ok := <-c2 // 数据已取完 程序到这里会出错 deadlock
fmt.Println(v,ok)
}

对于已关闭的管道,可以在取完数据时结束等待goroutine执行

for {
_, ok := <- exitChan bool
if !ok {
break
}
}

未关闭的channel需要取出指定个数的值之后结束等待goroutine执行

channel使用细节

channel默认是既可以读又可以写的

可以声明为只读或只写

var c1 <- chan int // 只读
var c2 chan <- int // 只写

一般channel不会声明为只读和只写,而是在声明函数形参的时候使用

var c1 chan string

func sendData(c chan <- string) {...}

func readData(c <- chan string) {...}

// c1是默认可读可写的channel
// 当c1作为参数传给 sendData时 在 sendData 函数中只允许对管道进行写操作
// 当c1作为参数传给 readData时 在 readData 函数中只允许对管道进行读操作

goroutine中使用recover函数解决协程中出现的panic ,不影响主线程的执行

defer func() {
if err = recover(); err != nil {
...dosomething
}
}

select

select用于解决从管道中取数据的阻塞问题

不使用select,在遍历未关闭的管道时会deadlock

然而,很多情况下管道都是未关闭的,因为不好确定什么时候关

用select来遍历未关闭管道,不会deaklock

func main() {
c1 := make(chan int, 10)
c2 := make(chan string, 5)
for i := 0; i < 10; i++ {
rand.Seed(time.Now().UnixNano())
c1 <- rand.Intn(100)
}
c2 <- "commerce"
c2 <- "corresponding"
c2 <- "oblige"
c2 <- "decline"
c2 <- "praise" label1:
for {
select {
case v := <-c1:
fmt.Println(v)
case v := <-c2:
fmt.Println(v)
default:
fmt.Println("两个管道都没数据了吧")
break label1
}
} fmt.Println("adhere")
}

golang管道的更多相关文章

  1. golang 管道

    2.管道简介Golang的原子并发特性使得它很容易构造流数据管道,这使得Golang可有效的使用I/O和多CPU特性.本文提出一些关于管道的示例,在这个过程中突出了操作失败的微妙之处和介绍处理失败的具 ...

  2. golang中管道热替换

    golang中管道替换问题 https://blog.csdn.net/cyk2396/article/details/78875347 1.运行以下代码: var chan1 chan int va ...

  3. golang channle 管道

    管道的使用介绍 现在要计算 1-N 的各个数的阶乘,并且把各个数的阶乘放入到 map 中.最后显示出来.要求使用 goroutine 完成 package main import ( "fm ...

  4. Golang, 以17个简短代码片段,切底弄懂 channel 基础

    (原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的IM服务器,所以复习了下之前一直没怎么使用的协程.管道等高并发编程知识 ...

  5. channel Golang

    Golang, 以17个简短代码片段,切底弄懂 channel 基础 (原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的 ...

  6. Golang 语法学习笔记

    Golang 语法学习笔记 包.变量和函数. 包 每个 Go 程序都是由包组成的. 程序运行的入口是包 main. 包名与导入路径的最后一个目录一致."math/rand" 包由 ...

  7. 【GoLang】golang 的精髓--流水线,对现实世界的完美模拟

    直接上代码: package main import ( "fmt" "runtime" "strconv" "sync" ...

  8. PHP与Golang如何通信?

    PHP与Golang如何通信? 最近遇到的一个场景:php项目中需要使用一个第三方的功能(结巴分词),而github上面恰好有一个用Golang写好的类库.那么问题就来了,要如何实现不同语言之间的通信 ...

  9. 【GoLang】并发小结

    006.并发 1 概念 1.1 goroutine是Go并行设计的核心,goroutine的本质是轻量级线程 1.2 golang的runtime实现了对轻量级线程即goroutine的智能调度管理 ...

随机推荐

  1. React Native移动开发实战-2-如何调试React Native项目

    在实际开发中,还有一个影响开发效率的重要因素:调试. 在1.4.3节中已经介绍了Enable Live Debugger的使用.本节来介绍另一个非常重要的调试选项:Debug JSRemotely选项 ...

  2. NO.8:自学python之路------并行socket网络编程

    摘要 一到放假就杂事很多,这次的作业比较复杂,做了一个周,进度又拖了.不过结果还不错. 正文 粘包 在上一节中,如果连续发送过多数据,就可能发生粘包.粘包就是两次发送的数据粘在一起被接收,损坏了数据的 ...

  3. Navicat新建查询,系统找不到指定路径 独家解决办法

    Navicat新建查询系统找不到指定路径,很多人用了网上流行的那些解决办法,还是无法解决.比如: https://jingyan.baidu.com/article/86112f1387a713273 ...

  4. 虚拟机搭建Hadoop集群

    安装包准备 操作系统:ubuntu-16.04.3-desktop-amd64.iso 软件包:VirtualBox 安装包:hadoop-3.0.0.tar.gz,jdk-8u161-linux-x ...

  5. 随手记录-linux-常用命令

    转自:https://www.cnblogs.com/yjd_hycf_space/p/7730690.html linux目录结构:http://www.cnblogs.com/fat39/p/72 ...

  6. Scrum Meeting 10.29

    成员 今日活动 明日计划 用时 徐越 配置tomcat+eclipse 将上届后端代码迁移到服务器 4h 赵庶宏 与数据库连接的java代码学习及编写,测试代码 进行数据库的建立并学习数据库方面的知识 ...

  7. java第三次试验报告

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计   班级:1353       姓名:郭皓  学号:20135327 成绩:             指导 ...

  8. sprint冲刺(第二天)

    今天的每日立会是在早上早餐后8点在宿舍讨论的,大概讨论了关于四则运算练习器APP的看法,也对一些较为基础的功能进行说明

  9. ini_set的权限大于error_reporting

    在用php做网站开发的时候 , 为防止用户看到错误信息,而出现的不友好界面.故一般性会在php.ini里设置:display_errors = Off;不过在开发的时候,我们有时候需要打开错误信息.这 ...

  10. Oracle 默认的driectory 目录

    1. 写导出命令忘记加directory参数了.. 查了一下: select directory_path from all_directories c:\cwdata\ C:\app\Adminis ...