1、未初始化的channel读,阻塞

package main

import (
"fmt"
"time"
) func main() {
var ch chan int
go check(ch) fmt.Println("main runtime end")
time.Sleep(time.Second * 1000)
} func check(ch chan int) {
select {
case i := <-ch:
fmt.Println("read ch data=", i)
}
fmt.Println("check runtime exit")
}

2、未初始化的channel写,阻塞

package main

import (
"fmt"
"time"
) func main() {
go func() {
for {
time.Sleep(time.Second * 1)
}
}()
var ch chan int
go check(ch)
time.Sleep(time.Second * 1)
fmt.Println("xxxxxxx")
<-ch
fmt.Println("main runtime end")
time.Sleep(time.Second * 1000)
} func check(ch chan int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("recover ", r)
}
}()
ch <- 1
fmt.Println("check runtime exit")
}

3、向已关闭的channel读,返回默认值和false

package main

import (
"fmt"
"time"
) func main() {
var ch chan int
ch = make(chan int)
go check(ch) fmt.Println("main runtime end")
close(ch)
time.Sleep(time.Second * 1000)
} func check(ch chan int) {
select {
case i, k := <-ch:
fmt.Println("read ch data=", i, " k=", k) //k=false i=0
}
fmt.Println("check runtime exit")
}

4、向已关闭的channel写,panic

package main

import (
"fmt"
"time"
) func main() {
var ch chan int
ch = make(chan int)
close(ch)
ch <- 1
fmt.Println("end")
time.Sleep(time.Second * 1000)
}

5、time.Timer Stop后,time.Timer.C将阻塞

package main

import (
"fmt"
"time"
) func main() {
tm := time.NewTimer(time.Second * 3)
go check(tm)
time.Sleep(time.Second * 1)
tm.Stop()
fmt.Println("main runtime end")
time.Sleep(time.Second * 1000)
} func check(tm *time.Timer) {
select {
case i, k := <-tm.C: //阻塞
fmt.Println("read ch data=", i, " k=", k)
}
fmt.Println("check runtime exit")
}

6、无缓冲与有缓冲channel的重要区别,无缓冲的channel在写时必须有读携程,否则会阻塞。如下例子,超时后向exit发数据会阻塞,因为只有一个携程,此时没有其他携程对exit进行读。【踩了坑才理解深刻】

package main

import (
"fmt"
"time"
) func main() {
exit := make(chan int)
go check(exit)
time.Sleep(time.Second * 100)
} func check(exit chan int) {
tm := time.NewTimer(time.Second * 3)
select {
case <-exit:
fmt.Println("exit")
case <-tm.C:
fmt.Println("time out")
exit <- 1
fmt.Println("exit <- 1 ok")
}
fmt.Println("check runtime exit")
}

例子2:

package main

import (
"fmt"
"time"
) func main() {
go func() {
for {
time.Sleep(time.Second * 1)
} }()
exit := make(chan int, 1)
exit <- 1
fmt.Println("end")
}

这里会直接END,如果exit:=make(chan int),会阻塞在exit<-1

golang channel 总结的更多相关文章

  1. golang channel的使用以及调度原理

    golang channel的使用以及调度原理 为了并发的goroutines之间的通讯,golang使用了管道channel. 可以通过一个goroutines向channel发送数据,然后从另一个 ...

  2. golang channel关闭后,是否可以读取剩余的数据

    golang channel关闭后,其中剩余的数据,是可以继续读取的. 请看下面的测试例子. 创建一个带有缓冲的channel,向channel中发送数据,然后关闭channel,最后,从channe ...

  3. golang channel原理

    channel介绍 channel一个类型管道,通过它可以在goroutine之间发送和接收消息.它是Golang在语言层面提供的goroutine间的通信方式. 众所周知,Go依赖于称为CSP(Co ...

  4. golang channel 用法转的

    一.Golang并发基础理论 Golang在并发设计方面参考了C.A.R Hoare的CSP,即Communicating Sequential Processes并发模型理论.但就像John Gra ...

  5. golang channel初次接触

    goroutine之间的同步 goroutine是golang中在语言级别实现的轻量级线程,仅仅利用go就能立刻起一个新线程.多线程会引入线程之间的同步问题,经典的同步问题如生产者-消费者问题,在c, ...

  6. 如何优雅的关闭Golang Channel?

    Channel关闭原则 不要在消费端关闭channel,不要在有多个并行的生产者时对channel执行关闭操作. 也就是说应该只在[唯一的或者最后唯一剩下]的生产者协程中关闭channel,来通知消费 ...

  7. golang channel几点总结

    golang提倡使用通讯来共享数据,而不是通过共享数据来通讯.channel就是golang这种方式的体现. Channel 在golang中有两种channel:带缓存的和不带缓存. 带缓存的cha ...

  8. golang channel 源码剖析

    channel 在 golang 中是一个非常重要的特性,它为我们提供了一个并发模型.对比锁,通过 chan 在多个 goroutine 之间完成数据交互,可以让代码更简洁.更容易实现.更不容易出错. ...

  9. golang channel本质——共享内存

    channel是golang中很重要的概念,配合goroutine是golang能够方便实现并发编程的关键.channel其实就是传统语言的阻塞消息队列,可以用来做不同goroutine之间的消息传递 ...

  10. Golang channel 用法简介

    channel 是 golang 里相当有趣的一个功能,大部分时候 channel 都是和 goroutine 一起配合使用.本文主要介绍 channel 的一些有趣的用法. 通道(channel), ...

随机推荐

  1. UNIX发展史简介

    1965年贝尔实验室(Bell Labs).通用电气(General Electric)和麻省理工学院(MIT)欲共同打造MULTICS(Multiplexed Information and Com ...

  2. Sql server2008如何导入Excel文件数据?

    sql server 中如何使用Excel文件导入数据?我做个测试,首先建立一个测试表(民族表) --创建一个民族表-- create table BdsNation( Uid int not nul ...

  3. Win10系列:JavaScript页内导航

    页内导航是在一个页面内根据需要加载其他页面的内容,在开发基于JavaScript的Windows应用商店应用时,可以使用WinJS.Navigation.navigate函数传递要加载的页面地址并使用 ...

  4. Win10系列:WinJS库控件

    在介绍了如何使用标准的HTML控件以及WinJS库中提供的新控件之后,下面来着重介绍WinJS库中几种常用的控件. (1)ListView控件 在开发Windows应用商店应用时可以使用ListVie ...

  5. Uboot USB模式(RK3288变砖头的解决办法)

    RK3288启动后有三种模式,可以分别进行操作. 第一种是normal也就是正常的启动模式.这个模式无法刷固件.一般板子通电就是这个模式 第二种是loader模式.就是刷固件模式.这个模式可以刷各种i ...

  6. learning ddr RTT

    Rtt: Dynamic ODT.DDR3引入的新特性.在特定的应用环境下为了更好的在数据总线上改善信号完整性, 不需要特定的MRS命令即可以改变终结强度(或者称为终端匹配).在MR2中的A9和A10 ...

  7. window有哪些属性?

    self:self代表自己,相当于window. parent:返回父窗口. top:返回顶层窗口,和parent作用一样. opener:窗口开启者. status:设置窗口状态栏的文本.

  8. Git的基本使用(github)

    关于Git的基本使用: 上传本地文件到github仓库中 首先要有自己的github账号,新建仓库: saiku-3.9 其次 本地安装好 git , 在本地任意目录下新建目录 saiku-3.9, ...

  9. 向量空间模型(VSM)在文档相似度计算上的简单介绍

    C#实现在: http://blog.csdn.net/Felomeng/archive/2009/03/25/4023990.aspx 向量空间模型(VSM:Vector space model)是 ...

  10. 深入理解java虚拟机---虚拟机工具jps与jstat(十四)

    jps-java process status jps类似于linux的ps命令,用于查看进程. JPS 名称: jps - Java Virtual Machine Process Status T ...