教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 Golang channel 使用指南

Golang channel 使用指南

发布时间:2022-01-25   编辑:jiaochengji.com
教程集为您提供Golang channel 使用指南等资源,欢迎您收藏本站,我们将为您提供最新的Golang channel 使用指南资源
<h3>基本介绍</h3>

通道(chan)是goroutine之间传递特定值的通信机制。它属于<code>通信顺序进程</code>并发模式(Communicating sequential processes,CSP)。go语言中还有另一种并发模式,即共享内存多线程的传统模型。

<h4>三种类型划分</h4>

接下来讨论chan的不同类型,从三个角度去分析:

<h5>缓冲/非缓冲(buffered/unbuffered)</h5>

chan是一个有长度的容器,通过对长度的限定,可以定义不同类型的通道。

对于声明长度的chan,称之为缓冲通道

<pre><code>ch := make(chan int, 1024) // buffered chan</code></pre>

对于没有声明长度的chan,称之为非缓冲通道

<pre><code>ch := make(chan int) // unbuffered chan</code></pre>

两种类型的chan会有不同的特性

<ul><li>非缓冲chan对于读写两端的goroutine都会阻塞。</li><li>缓冲chan在容量为空时,读端goroutine会阻塞;在容量未满时,读写两端都不会阻塞;但是容量满了之后,写端会阻塞</li></ul><h5>获取/发送(send/receive)</h5>

对于chan有获取/发送两种操作,在声明的时候可以限定使用的方式

<ul><li>获取/发送双向chan:</li></ul><pre><code>// chan T type goWorker struct { pool *Pool task chan func() recycleTime time.Time }</code></pre><ul><li>只获取chan:</li></ul><pre><code>// <-chan T 常见作为参数传递 func After(d Duration) <-chan Time { return NewTimer(d).C }</code></pre><ul><li>只发送chan:</li></ul><pre><code>// chan<-T 使用较少 func signalError(c chan<- error, err error) { select { case c <- err: default: } }</code></pre><h5>关闭(close)</h5>

chan不仅有长度,还可以被关闭,在被关闭后停止传递特定值。由此引出chan不同的状态:<code>空/empty</code>,<code>满/full</code>,<code>关闭/closed</code>

chan在关闭状态下,读取操作得到通道对应类型的空值,发送操作则会触发<code>panic</code>

<pre><code>done := make(chan struct{}, 1) close(done) d := <-done // {}</code></pre><pre><code>done := make(chan struct{}, 1) close(done) done <- struct{}{} //panic: send on closed channel</code></pre><h4>原理</h4>

chan在运行时内部由结构体<code>runtime.hchan</code>实现,想要深入了解可以阅读 源码,还可以参考阅读 draveness的Go语言设计与实现。在此不做赘述。

<h3>使用指南</h3>

这是本文的核心章节,通过举例来展示chan的使用场景。

<h4>使用方法</h4>

chan在实际使用时,通常会结合<code>for</code>和<code>select</code>

<ul><li>for/range - 持续循环</li></ul>

例子:godoc/context

<pre><code>for { select { case <-ctx.Done(): return // returning not to leak the goroutine case dst <- n: n } }</code></pre><ul><li>select - 随机选择</li></ul>

例子:apache/rocketmq-client-go

<pre><code>select { case <-time.Tick(time.Minute * time.Duration(bp.testMinutes)): case <-signalChan: }</code></pre><h4>使用案例</h4><ul><li>chan常见用于传递基本类型和结构体。</li></ul>

自带库:time/After,context/WithCancel

<pre><code>type Timer struct { C <-chan Time r runtimeTimer }</code></pre><pre><code>type cancelCtx struct { Context mu sync.Mutex // protects following fields done chan struct{} // created lazily, closed by first cancel call children map[canceler]struct{} // set to nil by the first cancel call err error // set to non-nil by the first cancel call }</code></pre><ul><li>chan不仅可以传递基本类型与结构体,还可以传递函数。</li></ul>

开源库:ants/worker

<pre><code>type goWorker struct { // pool who owns this worker. pool *Pool // task is a job should be done. task chan func() // recycleTime will be update when putting a worker back into queue. recycleTime time.Time }</code></pre><ul><li>在实际工程中,通常会在主程序入口进行signal监听,据此实现安全退出机制。</li></ul>

系统信号:os/signal

<pre><code>c := make(chan os.Signal, 1) signal.Notify(c) s := <-c fmt.Println("Got signal:", s)</code></pre>

总结:在实际工程代码中,常见三种值类型

<ul><li>基本类型&结构体</li><li>os.Signal</li><li>func()</li></ul><h4>工程问题</h4>

工程开发中会遇到类似这样的问题:何时使用chan?对比mq如何取舍?

整理如下几点使用chan考虑的因素:

<ul><li>所在goroutine持续运行:chan在常驻程序的不同goroutine之间传递信息</li><li>读写端,在同一程序运行:读写两端解耦但有关联,作为整体对外提供功能</li><li>适度缓存,做好丢失处理:作为内部信息传递通道,要考虑信息丢失的情况</li></ul><h3>引申探讨</h3>

无论是工程实践还是面试考察,以下引申话题都值得大家去探究。

<ul><li>goroutine:要了解chan的原理以及灵活使用chan,就不可绕过对goroutine的深入理解</li><li>select: 是chan常见的使用搭配,背后的机制值得分析</li><li>context:context是工程中一定会用到的语法实现,它的背后有chan的支撑</li></ul>

mjlzz备注:文章供大家交流讨论,欢迎指正

<h3>相关链接</h3><ol><li>Golang Channel最佳实践之基本规则</li><li>go101 Channels in Go</li><li>golang chan 源码</li><li>draveness的Go语言设计与实现</li><li>Golang 非阻塞 channel</li></ol> 到此这篇关于“Golang channel 使用指南”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
【文末有惊喜!】一文读懂golang channel
图解Go的channel底层原理
Golang channel 使用指南
Golang学习小结、从入门到精通资料汇总
golang channel的使用以及调度原理
golang基础教程
Go并发模式:管道和取消
Go 语言为什么这么快,带你详细了解Golang CSP并发模型
Golang之消息机制channel
golang 面试题(三)管道chan

[关闭]
~ ~