输出: 这种情况并不是报错空指针,而是死锁。加上make看看 输出 这种情况没什么毛病,之所以先输出的read,是因为IO机制。下面给写加上for 输出 报错说所有的协程都睡着,意思就是runtime发现没有能拿来调度的协程了,报错退出。如果是在大项目中,这里则会阻塞,runtime会调度其他可运行的协程。下面把for移到读操作上。 输出 跟上面现象基本一样,不再赘述,然后给俩操作都加上for 输出 结果当然就是死循环了,这个很好理解。接下来才是本文的重点:读数据的第二个参数。我们先保持其他的都不动,在读的时候接收第二个返回值。 输出 可以看出来,这第二个返回值是个bool类型,目前全都是true。那么什么时候会是false呢,把channel关上试试。为了更直观,把字符串的长度一起输出 输出 接下来就是很规律的死循环了。这样是不是可以猜测,从已经close的channle读数据,会读到该数据类型的零值,且第二个返回值为false?再试试给channel加个buffer,先写完关上再开始读 输出 我们把写操作前的 输出 很明显跟上面现象一致,如果忘了关闭channel呢? 输出 又睡着了,然后报错。跟上面情况一样,如果是在大项目中,runtime会调度其他可运行的协程。最后来总结一下怎么操作才算优(sao)雅(qi)。文章目录
用var定义channel且不make
wg := sync.WaitGroup{} var ch chan string read := func() { fmt.Println("reading") s := <-ch fmt.Println("read:", s) wg.Done() } write := func() { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) wg.Done() } wg.Add(2) go read() go write() fmt.Println("waiting") wg.Wait()
waiting writing reading fatal error: all goroutines are asleep - deadlock!
用var定义channel且make
wg := sync.WaitGroup{} var ch = make(chan string) read := func() { fmt.Println("reading") s := <-ch fmt.Println("read:", s) wg.Done() } write := func() { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) wg.Done() } wg.Add(2) go read() go write()
waiting writing reading read: t write: t
直给写操作加for
wg := sync.WaitGroup{} var ch = make(chan string) read := func() { fmt.Println("reading") s := <-ch fmt.Println("read:", s) wg.Done() } write := func() { for { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) } wg.Done() } wg.Add(2) go read() go write() fmt.Println("waiting") wg.Wait() fmt.Println("finish")
waiting reading writing write: t writing read: t fatal error: all goroutines are asleep - deadlock!
直给读操作加for
wg := sync.WaitGroup{} var ch = make(chan string) read := func() { for { fmt.Println("reading") s := <-ch fmt.Println("read:", s) } wg.Done() } write := func() { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) wg.Done() } wg.Add(2) go read() go write() fmt.Println("waiting") wg.Wait() fmt.Println("finish")
waiting reading writing write: t read: t reading fatal error: all goroutines are asleep - deadlock!
读写都加for
wg := sync.WaitGroup{} var ch = make(chan string) read := func() { for { fmt.Println("reading") s := <-ch fmt.Println("read:", s) } wg.Done() } write := func() { for { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) } wg.Done() } wg.Add(2) go read() go write() fmt.Println("waiting") wg.Wait() fmt.Println("finish")
waiting writing reading read: t write: t writing reading read: t reading write: t writing write: t writing ...
读channel的第二个返回值
wg := sync.WaitGroup{} var ch = make(chan string) read := func() { for { fmt.Println("reading") s, ok := <-ch fmt.Println("read:", s, ok) } wg.Done() } write := func() { for { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) } wg.Done() } wg.Add(2) go read() go write() fmt.Println("waiting") wg.Wait() fmt.Println("finish")
waiting writing reading read: t true reading write: t writing write: t writing read: t true reading read: t true reading write: t ...
关闭channel继续读
wg := sync.WaitGroup{} var ch = make(chan string) read := func() { for { fmt.Println("reading") s, ok := <-ch fmt.Println("read:", len(s), s, ok) } wg.Done() } write := func() { for i := 0; i < 5; i++ { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) } wg.Done() close(ch) } wg.Add(2) go read() go write() fmt.Println("waiting") wg.Wait() fmt.Println("finish")
waiting writing reading read: 1 t true reading write: t writing write: t writing read: 1 t true reading read: 1 t true reading write: t writing write: t writing read: 1 t true reading read: 1 t true reading write: t read: 0 false reading read: 0 false reading read: 0 false ...
写完然后关闭channel再开始读
wg := sync.WaitGroup{} var ch = make(chan string, 5) read := func() { for { fmt.Println("reading") s, ok := <-ch fmt.Println("read:", len(s), s, ok) } wg.Done() } write := func() { for i := 0; i < 5; i++ { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) } wg.Done() close(ch) fmt.Println("closed") } wg.Add(2) write() go read() fmt.Println("waiting") wg.Wait() fmt.Println("finish")
writing write: t writing write: t writing write: t writing write: t writing write: t closed waiting reading read: 1 t true reading read: 1 t true reading read: 1 t true reading read: 1 t true reading read: 1 t true reading read: 0 false reading read: 0 false reading read: 0 false ...
go
关键字去了,并且在关闭channel之后加了log。可以很清晰的看到,先往channel里写了5次,然后close了,之后才有wait及read的log。并且前5个ok是true,后面循环输出false。现在我们可以得出结论当channel关闭且数据都读完了,再读数据会读到该数据类型的零值,且第二个返回值为false。下面再套上select加个select
wg := sync.WaitGroup{} var ch = make(chan string, 5) read := func() { for { fmt.Println("reading") select { case s, ok := <-ch: fmt.Println("read:", len(s), s, ok) } } wg.Done() } write := func() { for i := 0; i < 5; i++ { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) } wg.Done() close(ch) fmt.Println("closed") } wg.Add(2) write() go read() fmt.Println("waiting") wg.Wait() fmt.Println("finish")
writing write: t writing write: t writing write: t writing write: t writing write: t closed waiting reading read: 1 t true reading read: 1 t true reading read: 1 t true reading read: 1 t true reading read: 1 t true reading read: 0 false reading read: 0 false reading read: 0 false ...
channel未及时关闭
wg := sync.WaitGroup{} var ch = make(chan string, 5) read := func() { for { fmt.Println("reading") select { case s, ok := <-ch: fmt.Println("read:", len(s), s, ok) } } wg.Done() } write := func() { for i := 0; i < 5; i++ { fmt.Println("writing") s := "t" ch <- s fmt.Println("write:", s) } wg.Done() //close(ch) //fmt.Println("closed") } wg.Add(2) write() go read() fmt.Println("waiting") wg.Wait() fmt.Println("finish")
writing write: t writing write: t writing write: t writing write: t writing write: t waiting reading read: 1 t true reading read: 1 t true reading read: 1 t true reading read: 1 t true reading read: 1 t true reading fatal error: all goroutines are asleep - deadlock!
总结
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算