1、记一次gorountine导致的泄漏

在项目中使用https://github.com/deckarep/golang-set这个三方包造成了gorountine泄漏。先来看一下这个包的迭代器设置,如下:

  1. package mapset
  2.  
  3. // Iterator defines an iterator over a Set, its C channel can be used to range over the Set's
  4. // elements.
  5. type Iterator struct {
  6. C <-chan interface{}
  7. stop chan struct{}
  8. }
  9.  
  10. // Stop stops the Iterator, no further elements will be received on C, C will be closed.
  11. func (i *Iterator) Stop() {
  12. // Allows for Stop() to be called multiple times
  13. // (close() panics when called on already closed channel)
  14. defer func() {
  15. recover()
  16. }()
  17.  
  18. close(i.stop)
  19.  
  20. // Exhaust any remaining elements.
  21. for range i.C {
  22. }
  23. }
  24.  
  25. // newIterator returns a new Iterator instance together with its item and stop channels.
  26. func newIterator() (*Iterator, chan<- interface{}, <-chan struct{}) {
  27. itemChan := make(chan interface{})
  28. stopChan := make(chan struct{})
  29. return &Iterator{
  30. C: itemChan,
  31. stop: stopChan,
  32. }, itemChan, stopChan
  33. }

这样,向外提供API时的代码如下:

  1. func (set *threadSafeSet) Iterator() *Iterator {
  2. iterator, ch, stopCh := newIterator()
  3.  
  4. go func() {
  5. set.RLock()
  6. L:
  7. for elem := range set.s {
  8. select {
  9. case <-stopCh:
  10. break L
  11. case ch <- elem:
  12. }
  13. }
  14. close(ch)
  15. set.RUnlock()
  16. }()
  17.  
  18. return iterator
  19. }  

正确的使用方法如下:

  1. type YourType struct {
  2. Name string
  3. }
  4.  
  5. func ExampleIterator() {
  6. set := NewSetFromSlice([]interface{}{
  7. &YourType{Name: "Alise"},
  8. &YourType{Name: "Bob"},
  9. &YourType{Name: "John"},
  10. &YourType{Name: "Nick"},
  11. })
  12.  
  13. var found *YourType
  14. it := set.Iterator()
  15.  
  16. for elem := range it.C {
  17. if elem.(*YourType).Name == "John" {
  18. found = elem.(*YourType)
  19. it.Stop()
  20. }
  21. }
  22.  
  23. fmt.Printf("Found %+v\n", found)
  24.  
  25. // Output: Found &{Name:John}
  26. }

  

还有另外一个方法,如下:  

  1. func (set *threadSafeSet) Iter() <-chan interface{} {
  2. ch := make(chan interface{})
  3. go func() {
  4. set.RLock()
  5.  
  6. for elem := range set.s {
  7. ch <- elem
  8. }
  9. close(ch)
  10. set.RUnlock()
  11. }()
  12.  
  13. return ch
  14. }

这个方法必须遍历完所有的elem元素,否则会造成gorountine阻塞。所以切不可在循环之内break。  

2、理解chan chan类型

一个小Demo有助于理解,代码如下:

  1. import (
  2. "time"
  3. "fmt"
  4. )
  5.  
  6. func main() {
  7.  
  8. // make the request chan chan that both go-routines will be given
  9. requestChan := make(chan chan string)
  10.  
  11. // start the goroutines
  12. go goroutineC(requestChan)
  13. go goroutineD(requestChan)
  14.  
  15. // sleep for a second to let the goroutines complete
  16. time.Sleep(time.Second)
  17.  
  18. }
  19.  
  20. func goroutineC(requestChan chan chan string) {
  21.  
  22. // make a new response chan
  23. responseChan := make(chan string)
  24.  
  25. // send the responseChan to goRoutineD
  26. requestChan <- responseChan
  27.  
  28. // read the response
  29. response := <-responseChan
  30.  
  31. fmt.Printf("Response: %v\n", response)
  32.  
  33. }
  34.  
  35. func goroutineD(requestChan chan chan string) {
  36.  
  37. // read the responseChan from the requestChan
  38. responseChan := <-requestChan
  39.  
  40. // send a value down the responseChan
  41. responseChan <- "wassup!"
  42.  
  43. }

chan chan类型有非常大的用处,如实现每分钟百万流量的处理。

  

参考:

(1)http://tleyden.github.io/blog/2013/11/23/understanding-chan-chans-in-go/

(2)https://www.goin5minutes.com/blog/channel_over_channel/

(3)http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang/

关于go语言的通道的更多相关文章

  1. Go语言的通道(1)-无缓冲通道

    前言: 上文中我们采用了[原子函数]已经[共享锁]两种方式分别对多个goroutine进行了同步,但是在go语言中提供了另一种更好的方式,那就是使用通道(Channel). 一.通道是什么? 其实无论 ...

  2. Go语言的通道(2)-缓冲通道

    有缓冲的通道相比于无缓冲通道,多了一个缓存的功能,如下图描述的一样: 从图上可以明显看到和无缓冲通道的区别,无缓冲必须两个Goroutine都进入通道才能进行数据的交换,这个不用,如果数据有,直接就能 ...

  3. Go语言规格说明书 之 通道 发送语句(send) 和 接收操作符(receive)

    go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...

  4. Go语言规格说明书 之 通道类型(Channel types)

    go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...

  5. 027_go语言中的通道选择器

    代码演示 package main import "fmt" import "time" func main() { c1 := make(chan strin ...

  6. Go语言程序设计(1)--基本语法

    第一个程序 package main import "fmt" func main() { fmt.Printf("Hello world") } 通过阅读这个 ...

  7. 掌握一门语言Go

    摘要:Go语言的优势不必多说,通过本篇文章,让我们花时间来掌握一门外语,Let's Go! 关键字:Go语言,闭包,基本语法,函数与方法,指针,slice,defer,channel,goroutin ...

  8. Go语言之并发编程(二)

    通道(channel) 单纯地将函数并发执行是没有意义的.函数与函数间需要交换数据才能体现并发执行函数的意义.虽然可以使用共享内存进行数据交换,但是共享内存在不同的goroutine中容易发生竞态问题 ...

  9. 高手问答精选:Go 语言 —— 云计算时代的 C 语言(类似于一个FAQ)

    Go 语言被称为云计算时代的 C 语言,它在软件开发效率和运行效率之间做出了绝佳的权衡.这使得它既适应于互联网应用的极速开发,又能在高并发.高性能的开发场景中如鱼得水.正因如此,许多互联网公司,尤其是 ...

随机推荐

  1. Tcl与Design Compiler (五)——综合库(时序库)和DC的设计对象

    本文如果有错,欢迎留言更正:此外,转载请标明出处 http://www.cnblogs.com/IClearner/  ,作者:IC_learner 前面一直说到综合库/工艺库这些东西,现在就来讲讲讲 ...

  2. Python:使用youtube-dl+ffmpeg+FQ软件下载youtube视频

    声明:本文所述内容都是从http://blog.csdn.net/u011475134/article/details/71023612博文中学习而来. 背景: 一同学想通过FQ软件下载一些youtu ...

  3. Windows10 64位系统安装 .NET Framework 3.5

    1)下载NET Framework 3.5 [地址:https://pan.baidu.com/s/1c1FhXLY] 2)编辑NET Framework 3.5.bat ,修改sxs文件存放路径: ...

  4. js常用正则表达式表单验证代码

    方法一:  var re=/正则表达式/;  re.test($("txtid").val())  方法二:  $("txtid").val.match(/正则 ...

  5. SQL知识点

    关系型数据库:MySql非关系型数据库:Redis(以键值对的方式) SQL分几类: DDL:数据定义语言:create.alter.drop.truncate DML:数据操作语言:insert.d ...

  6. C# WinForm 富文本编辑器 用kindeditor实现本地图片只选取不上传到编辑器

    以下资料有参考网上其它童鞋作品,原作者看到务喷!!!! 以下资料有参考网上其它童鞋作品,原作者看到务喷!!!! 重要的事只要说两遍... 网上找了几天关于WinForm富文本编辑效果都不理想,各种坑, ...

  7. jsonViewer json格式化工具

    以前一直以来都觉得xml个可读性要比json的可读性好,后来使用了JSON Viewer这个小工具之后,发现自己错了.之前认为json的可读性差,完全是因为没有很好的查看工具.JSON Viewer这 ...

  8. MySQL-分组查询(GROUP BY)及二次筛选(HAVING)

    为了测试GROUP BY 语句,我们创建两张表,并往表中添加数据 -- 创建部门表 CREATE TABLE IF NOT EXISTS department( id TINYINT UNSIGNED ...

  9. [LeetCode] Pyramid Transition Matrix 金字塔转变矩阵

    We are stacking blocks to form a pyramid. Each block has a color which is a one letter string, like ...

  10. [LeetCode] Image Smoother 图片平滑器

    Given a 2D integer matrix M representing the gray scale of an image, you need to design a smoother t ...