关于go语言的通道
1、记一次gorountine导致的泄漏
在项目中使用https://github.com/deckarep/golang-set这个三方包造成了gorountine泄漏。先来看一下这个包的迭代器设置,如下:
package mapset
// Iterator defines an iterator over a Set, its C channel can be used to range over the Set's
// elements.
type Iterator struct {
C <-chan interface{}
stop chan struct{}
}
// Stop stops the Iterator, no further elements will be received on C, C will be closed.
func (i *Iterator) Stop() {
// Allows for Stop() to be called multiple times
// (close() panics when called on already closed channel)
defer func() {
recover()
}()
close(i.stop)
// Exhaust any remaining elements.
for range i.C {
}
}
// newIterator returns a new Iterator instance together with its item and stop channels.
func newIterator() (*Iterator, chan<- interface{}, <-chan struct{}) {
itemChan := make(chan interface{})
stopChan := make(chan struct{})
return &Iterator{
C: itemChan,
stop: stopChan,
}, itemChan, stopChan
}
这样,向外提供API时的代码如下:
func (set *threadSafeSet) Iterator() *Iterator {
iterator, ch, stopCh := newIterator()
go func() {
set.RLock()
L:
for elem := range set.s {
select {
case <-stopCh:
break L
case ch <- elem:
}
}
close(ch)
set.RUnlock()
}()
return iterator
}
正确的使用方法如下:
type YourType struct {
Name string
}
func ExampleIterator() {
set := NewSetFromSlice([]interface{}{
&YourType{Name: "Alise"},
&YourType{Name: "Bob"},
&YourType{Name: "John"},
&YourType{Name: "Nick"},
})
var found *YourType
it := set.Iterator()
for elem := range it.C {
if elem.(*YourType).Name == "John" {
found = elem.(*YourType)
it.Stop()
}
}
fmt.Printf("Found %+v\n", found)
// Output: Found &{Name:John}
}
还有另外一个方法,如下:
func (set *threadSafeSet) Iter() <-chan interface{} {
ch := make(chan interface{})
go func() {
set.RLock()
for elem := range set.s {
ch <- elem
}
close(ch)
set.RUnlock()
}()
return ch
}
这个方法必须遍历完所有的elem元素,否则会造成gorountine阻塞。所以切不可在循环之内break。
2、理解chan chan类型
一个小Demo有助于理解,代码如下:
import (
"time"
"fmt"
)
func main() {
// make the request chan chan that both go-routines will be given
requestChan := make(chan chan string)
// start the goroutines
go goroutineC(requestChan)
go goroutineD(requestChan)
// sleep for a second to let the goroutines complete
time.Sleep(time.Second)
}
func goroutineC(requestChan chan chan string) {
// make a new response chan
responseChan := make(chan string)
// send the responseChan to goRoutineD
requestChan <- responseChan
// read the response
response := <-responseChan
fmt.Printf("Response: %v\n", response)
}
func goroutineD(requestChan chan chan string) {
// read the responseChan from the requestChan
responseChan := <-requestChan
// send a value down the responseChan
responseChan <- "wassup!"
}
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语言的通道的更多相关文章
- Go语言的通道(1)-无缓冲通道
前言: 上文中我们采用了[原子函数]已经[共享锁]两种方式分别对多个goroutine进行了同步,但是在go语言中提供了另一种更好的方式,那就是使用通道(Channel). 一.通道是什么? 其实无论 ...
- Go语言的通道(2)-缓冲通道
有缓冲的通道相比于无缓冲通道,多了一个缓存的功能,如下图描述的一样: 从图上可以明显看到和无缓冲通道的区别,无缓冲必须两个Goroutine都进入通道才能进行数据的交换,这个不用,如果数据有,直接就能 ...
- Go语言规格说明书 之 通道 发送语句(send) 和 接收操作符(receive)
go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...
- Go语言规格说明书 之 通道类型(Channel types)
go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...
- 027_go语言中的通道选择器
代码演示 package main import "fmt" import "time" func main() { c1 := make(chan strin ...
- Go语言程序设计(1)--基本语法
第一个程序 package main import "fmt" func main() { fmt.Printf("Hello world") } 通过阅读这个 ...
- 掌握一门语言Go
摘要:Go语言的优势不必多说,通过本篇文章,让我们花时间来掌握一门外语,Let's Go! 关键字:Go语言,闭包,基本语法,函数与方法,指针,slice,defer,channel,goroutin ...
- Go语言之并发编程(二)
通道(channel) 单纯地将函数并发执行是没有意义的.函数与函数间需要交换数据才能体现并发执行函数的意义.虽然可以使用共享内存进行数据交换,但是共享内存在不同的goroutine中容易发生竞态问题 ...
- 高手问答精选:Go 语言 —— 云计算时代的 C 语言(类似于一个FAQ)
Go 语言被称为云计算时代的 C 语言,它在软件开发效率和运行效率之间做出了绝佳的权衡.这使得它既适应于互联网应用的极速开发,又能在高并发.高性能的开发场景中如鱼得水.正因如此,许多互联网公司,尤其是 ...
随机推荐
- 如何打开hprof文件
最近学习深入java虚拟机的书,照着里面的例子跑了下. 下面是demo: /** * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError * ...
- Properties文件读写问题
项目需要在Properties配置文件中设置一些配置属性,其中包含一些中文属性.经过一上午的奋斗终于圆满解决问题. 读取Properties文件所有属性 Map<String, String&g ...
- ios8新的api
self.navigationController.hidesBarsOnSwipe=YES; 滚动时隐藏导航栏
- Win10系统Python虚拟环境安装
1.安装virtualenv 若要使用python虚拟环境进行开发,首先需要安装virtualenv. 命令:pip install virtualenv 2.安装虚拟环境 命令:virtualenv ...
- 南阳OJ-2-括号配对问题---栈的应用
题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=2 题目大意: 有一行括号序列,请你检查这行括号是否配对. 思路: 直接用栈来模拟 ...
- read运行
#_*_ coding:utf-8 _*_ from sys import argv from os.path import exists script, from_file, to_file = ...
- STL迭代器------Traits编程技法详细理解(一)
最近在看STL源码解析的迭代器(iterators)一章,涉及到c++ Traits的编程技法,刚开始看时一头雾水,反复看了好几遍之后才理解这个东西,因此来写写在这方面的理解,如有错误,希望读者指正. ...
- LeakCanary检测内存泄漏.md
一使用步骤 添加依赖 // 内存泄漏检测 debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4' releaseCompile ...
- webstorm中github的配置
1.申请一个github账号,我这里的操作是已经有了账号的情况之下进行的. 打开webstorm,File-->settings,弹出settings框,输入git,得到以下界面,输入githu ...
- Ajax/XHR/HTTP/jQuery Ajax
Ajax即通过XHR API使用js发起的异步网络请求,它不会导致页面刷新,因此是现代Web App的关键技术. HTTP协议是Web开发中最重要的网络协议,HTTP协议详细规定了请求和响应报文. 请 ...