From e2e9c6bd30c8b566b5bf848a296f733001e4a279 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 10:52:04 +0800 Subject: [PATCH 01/20] Create 14.3.md --- eBook/14.3.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 eBook/14.3.md diff --git a/eBook/14.3.md b/eBook/14.3.md new file mode 100644 index 0000000..4020dbe --- /dev/null +++ b/eBook/14.3.md @@ -0,0 +1 @@ +# 协程的同步:关闭通道-测试阻塞的通道 From 1f352b20ea3eb05ea82a540f80710159ba7476fc Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 10:52:38 +0800 Subject: [PATCH 02/20] Update 14.2.md --- eBook/14.2.md | 1 - 1 file changed, 1 deletion(-) diff --git a/eBook/14.2.md b/eBook/14.2.md index 3db35a1..2d42fd4 100644 --- a/eBook/14.2.md +++ b/eBook/14.2.md @@ -626,7 +626,6 @@ func main() { } ``` - ## 链接 - [目录](directory.md) From dab7a34ab6865bacfe1401a05ab703d20712af07 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 11:24:27 +0800 Subject: [PATCH 03/20] Update 14.3.md --- eBook/14.3.md | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/eBook/14.3.md b/eBook/14.3.md index 4020dbe..b3d12fc 100644 --- a/eBook/14.3.md +++ b/eBook/14.3.md @@ -1 +1,110 @@ # 协程的同步:关闭通道-测试阻塞的通道 + +通道可以被显示的关闭;尽管它们和文件不同:不必每次都关闭。只有在当需要告诉接收者不会再提供新的值的时候,才需要关闭通道。只有发送者需要关闭通道,接收者永远不会需要。 + +继续看示例[goroutine2.go](examples/chapter_14/goroutine2.go)(示例14.2):我们如何在通道的`sendData()`完成的时候发送一个信号,`getData()`又如何检测到通道是否关闭或阻塞? + +第一个可以通过函数`close(ch)`来完成:这个将通道标记为无法通过发送操作<-接受更多的值;给已经关闭的通道发送或者再次关闭都会导致运行时的panic。在创建一个通道后使用defer语句是个不错的办法(类似这种情况): +```go +ch := make(chan float64) +defer close(ch) +``` +第二个问题可以使用逗号,ok操作符:用来检测通道是否被关闭。 + +如何来检测可以收到没有被阻塞(或者通道没有被关闭)? +```go +v, ok := <-ch // ok is true if v received value +``` +通常和if语句一起使用: +```go +if v, ok := <-ch; ok { + process(v) +} +``` +或者在for循环中接收的时候,当关闭或者阻塞的时候使用break: +```go +v, ok := <-ch +if !ok { + break +} +process(v) +``` +可以通过`_ = ch <- v`来实现非阻塞发送,因为空标识符获取到了发送给`ch`的任何东西。在示例程序14.2中使用这些可以改进为版本goroutine3.go,输出相同。 + +实现非阻塞通道的读取,需要使用select(参见章节[14.4](14.4.md)) + +示例 14.9-[goroutine3.go](examples/chapter_14/goroutine3.go) +```go +package main + +import "fmt" + +func main() { + ch := make(chan string) + go sendData(ch) + getData(ch) +} + +func sendData(ch chan string) { + ch <- "Washington" + ch <- "Tripoli" + ch <- "London" + ch <- "Beijing" + ch <- "Tokio" + close(ch) +} + +func getData(ch chan string) { + for { + input, open := <-ch + if !open { + break + } + fmt.Printf("%s ", input) + } +} +``` +改变了以下代码: +* 现在只有`sendData()`是协程,`getData()`和`main()`在同一个线程中: +```go +go sendData(ch) +getData(ch) +``` +* 在`sendData()`函数的最后,关闭了通道: +```go +func sendData(ch chan string) { + ch <- "Washington" + ch <- "Tripoli" + ch <- "London" + ch <- "Beijing" + ch <- "Tokio" + close(ch) +} +``` +* 在for循环的`getData()`中,在每次接收通道的数据之前都使用`if !open`来检测: +```go +for { + input, open := <-ch + if !open { + break + } + fmt.Printf("%s ", input) + } +``` +使用for-range语句来读取通道是更好的办法,因为这会自动检测通道是否关闭: +```go +for input := range ch { + process(input) +} +``` +阻塞和生产者-消费者模式: + + + + + +## 链接 + +- [目录](directory.md) +- 上一节:[协程间的信道](14.2.md) +- 下一节:[使用select切换协程](14.4.md) From ffc52b698fa6fb5710b5be31e984b9485e11ecf9 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 11:24:54 +0800 Subject: [PATCH 04/20] Update 14.3.md --- eBook/14.3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eBook/14.3.md b/eBook/14.3.md index b3d12fc..e2e2372 100644 --- a/eBook/14.3.md +++ b/eBook/14.3.md @@ -94,7 +94,7 @@ for { 使用for-range语句来读取通道是更好的办法,因为这会自动检测通道是否关闭: ```go for input := range ch { - process(input) + process(input) } ``` 阻塞和生产者-消费者模式: From 9c8a85c98b669a2d62201277441a81a415e121c6 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 14:23:01 +0800 Subject: [PATCH 05/20] =?UTF-8?q?=E5=AE=8C=E6=88=90=2014.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/14.3.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eBook/14.3.md b/eBook/14.3.md index e2e2372..632f25d 100644 --- a/eBook/14.3.md +++ b/eBook/14.3.md @@ -1,4 +1,4 @@ -# 协程的同步:关闭通道-测试阻塞的通道 +# 14.3 协程的同步:关闭通道-测试阻塞的通道 通道可以被显示的关闭;尽管它们和文件不同:不必每次都关闭。只有在当需要告诉接收者不会再提供新的值的时候,才需要关闭通道。只有发送者需要关闭通道,接收者永远不会需要。 @@ -99,9 +99,9 @@ for input := range ch { ``` 阻塞和生产者-消费者模式: +在章节14.2.10的通道迭代器中,两个协程经常是一个阻塞另外一个。如果程序工作在多核心的机器上,大部分时间只用到了一个处理器。可以通过使用带缓冲(缓冲空间大于0)的通道来改善。比如,缓冲大小为100,迭代器在阻塞之前,至少可以从容器获得100个元素。如果消费者协程在独立的内核运行,就有可能让协程不会出现阻塞。 - - +由于容器中元素的数量通常是已知的,需要让通道有足够的容量放置所有的元素。这样,迭代器就不会阻塞(尽管消费者协程仍然可能阻塞)。然后,这样有效的加倍了迭代容器所需要的内存使用量,所以通道的容量需要限制一下最大值。记录运行时间和性能测试可以帮助你找到最小的缓存容量带来最好的性能。 ## 链接 From e30ff8107933ba5a3ba16112a38e786c31593900 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 14:34:53 +0800 Subject: [PATCH 06/20] Create 14.4 --- eBook/14.4 | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 eBook/14.4 diff --git a/eBook/14.4 b/eBook/14.4 new file mode 100644 index 0000000..b509708 --- /dev/null +++ b/eBook/14.4 @@ -0,0 +1,8 @@ +# 14.4 使用select切换协程 + + +## 链接 + +- [目录](directory.md) +- 上一节:[通道的同步:关闭通道-测试阻塞的通道](14.3.md) +- 下一节:[通道,超时和计时器](14.5.md) From ae5dbe4a0651a44833834060bf7f3ac71cb1f655 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 14:36:19 +0800 Subject: [PATCH 07/20] Rename 14.4 to 14.4.md --- eBook/{14.4 => 14.4.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename eBook/{14.4 => 14.4.md} (100%) diff --git a/eBook/14.4 b/eBook/14.4.md similarity index 100% rename from eBook/14.4 rename to eBook/14.4.md From e357fc09c2d164cfe815fd52e1a7a53df843fb3d Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 15:18:30 +0800 Subject: [PATCH 08/20] Update 14.4.md --- eBook/14.4.md | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/eBook/14.4.md b/eBook/14.4.md index b509708..516b43d 100644 --- a/eBook/14.4.md +++ b/eBook/14.4.md @@ -1,5 +1,89 @@ # 14.4 使用select切换协程 +从不不同的并发执行的协程中获取值可以通过关键字`select`来完成,它和`switch`控制语句非常相似(章节5.3)也被称作通信开关;它的行为像是“你准备好了吗”的轮询机制;`select`监听进入通道的数据,也可以是用通道发送值的时候。 +```go +select { +case u:= <- ch1: + ... +case v:= <- ch2: + ... + ... +default: // no value ready to be received + ... +} +``` +`default`语句是可选的;fallthrough行为,和普通的switch相似,是不允许的。在任何一个case中执行`break`或者`return`,select就结束了。 + +`select`做得就是:选择处理列出的多个通信情况中的一个。 +* 如果都阻塞了,会等待直到其中一个可以处理 +* 如果多个可以处理,随机选择一个 +* 如果没有通道操作可以处理并且写了`default`语句,它就会执行:`default`永远是可运行的(这就是准备好了,可以执行)。 + +在`select`中使用发送操作并且有`default`可以确保发送不被阻塞!如果没有cases,select就会一直阻塞。 + +`select`语句实现了一种监听模式,通常用在(无限)循环中;在某种情况下,通过`break`语句使循环退出。 + +在程序[goroutine_select.go](examples/chapter_14/goroutine_select.go)中有2个通道`ch1`和`ch2`,三个协程`pump1()`,`pump2()`和`suck()`。这是一个典型的生产者消费者模式。在无限循环中,`ch1`和`ch2`通过`pump1()`和`pump2()`填充整数;`suck()`也是在无限循环中轮询输入的,通过`select`语句获取`ch1`和`ch2`的整数并输出。选择哪一个case取决于哪一个通道收到了信息。程序在main执行1秒后结束。 + +示例 14.10-[goroutine_select.go](examples/chapter_14/goroutine_select.go) +```go +package main + +import ( + "fmt" + "time" +) + +func main() { + ch1 := make(chan int) + ch2 := make(chan int) + + go pump1(ch1) + go pump2(ch2) + go suck(ch1, ch2) + + time.Sleep(1e9) +} + +func pump1(ch chan int) { + for i := 0; ; i++ { + ch <- i * 2 + } +} + +func pump2(ch chan int) { + for i := 0; ; i++ { + ch <- i + 5 + } +} + +func suck(ch1, ch2 chan int) { + for { + select { + case v := <-ch1: + fmt.Printf("Received on channel 1: %d\n", v) + case v := <-ch2: + fmt.Printf("Received on channel 2: %d\n", v) + } + } +} +``` +输出: +``` +Received on channel 2: 5 +Received on channel 2: 6 +Received on channel 1: 0 +Received on channel 2: 7 +Received on channel 2: 8 +Received on channel 2: 9 +Received on channel 2: 10 +Received on channel 1: 2 +Received on channel 2: 11 +... +Received on channel 2: 47404 +Received on channel 1: 94346 +Received on channel 1: 94348 +``` ## 链接 From f419fd486fcbc2d62d20c60033a415686c68d901 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 18:00:08 +0800 Subject: [PATCH 09/20] Update 14.4.md --- eBook/14.4.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/eBook/14.4.md b/eBook/14.4.md index 516b43d..220721d 100644 --- a/eBook/14.4.md +++ b/eBook/14.4.md @@ -84,6 +84,39 @@ Received on channel 2: 47404 Received on channel 1: 94346 Received on channel 1: 94348 ``` +一秒内的输出非常惊人,如果我们给它计数(goroutine_select2.go),得到了90000个左右的数字。 + +##练习: + +练习14.7: +* a)在练习5.4的for_loop.go中,有一个常见的for循环打印数字。在函数`tel`中实现一个for循环,用协程开始这个函数并在其中给通道发送数字。`main()`线程从通道中获取并打印。不要使用`time.Sleep()`来同步:[goroutine_panic.go](exercises/chapter_14/goroutine_panic.go) +* b)也许你的方案有效,可能会引发运行时的panic:`throw:all goroutines are asleep-deadlock!` 为什么会这样?你如何解决这个问题?[goroutine_close.go]((exercises/chapter_14/goroutine_close.go)) +* c)解决a)的另外一种方式:使用一个额外的通道传递给协程,然后在结束的时候随便放点什么进去。`main()`线程检查是否有数据发送给了这个通道,如果有就停止:[goroutine_select.go](exercises/chapter_14/goroutine_select.go) + + +练习14.8: + +从示例6.10的斐波那契程序开始,制定解决方案,使斐波那契周期计算独立到协程中,并可以把结果发送给通道。 + +结束的时候关闭通道。`main()`函数读取通道并打印结果:[goFibonacci.go](exercises/chapter_14/gofibonacci.go) + +使用练习6.9中的算法写一个更短的[gofibonacci2.go](exercises/chapter_14/gofibonacci2.go) + +使用`select`语句来写,并让通道退出([gofibonacci_select.go](exercises/chapter_14/gofibonacci_select.go)) + +注意:当给结果计时并和6.10对比时,我们发现使用通道通信的性能开销有轻微削减;这个例子中的算法使用协程并非性能最好的选择;但是[gofibonacci3](exercises/chapter_14/gofibonacci3.go)方案使用了2个协程带来了3倍的提速。 + + +练习14.9: + +做一个随机位生成器,程序可以提供无限的随机0或者1的序列:[random_bitgen.go](exercises/chapter_14/random_bitgen.go) + + +练习14.10:[polar_to_cartesian.go](exercises/chapter_14/polar_to_cartesian.go) + +(这是一种综合练习,使用到章节4,9,11的内容和本章内容。) + + ## 链接 From 14b1353816cbfed0c9c8400229111ac83fcf604d Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 18:21:47 +0800 Subject: [PATCH 10/20] Update README_gc.md --- README_gc.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README_gc.md b/README_gc.md index 5c8209c..9626c6f 100644 --- a/README_gc.md +++ b/README_gc.md @@ -37,3 +37,4 @@ Golang 编程:245386165 |2015-12-22|15.4 |2015-12-25|14.1 |2015-12-28|14.2 +|2015-12-30|14.3 14.4 From 1a531b7a1d72faf044225736311c1fe367e53258 Mon Sep 17 00:00:00 2001 From: glight2000 Date: Tue, 29 Dec 2015 18:25:56 +0800 Subject: [PATCH 11/20] add pi series image for chapter 14.4 --- images/14.4_piseries .png | Bin 0 -> 12906 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/14.4_piseries .png diff --git a/images/14.4_piseries .png b/images/14.4_piseries .png new file mode 100644 index 0000000000000000000000000000000000000000..d7c84b6f2ef1bc15cffa4f083ca348f1b29ab1f9 GIT binary patch literal 12906 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 OQIu7ash0W@`hNhW2~)fP literal 0 HcmV?d00001 From 8d05c6d56d318ea4c1948c17b620eade12f7ae55 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 18:28:36 +0800 Subject: [PATCH 12/20] Update 14.4.md --- eBook/14.4.md | 1 - 1 file changed, 1 deletion(-) diff --git a/eBook/14.4.md b/eBook/14.4.md index 220721d..01180d5 100644 --- a/eBook/14.4.md +++ b/eBook/14.4.md @@ -117,7 +117,6 @@ Received on channel 1: 94348 (这是一种综合练习,使用到章节4,9,11的内容和本章内容。) - ## 链接 - [目录](directory.md) From f0c81a5d04d920598ae3c69e3cf4424dfd535828 Mon Sep 17 00:00:00 2001 From: glight2000 Date: Tue, 29 Dec 2015 18:30:10 +0800 Subject: [PATCH 13/20] rename image file --- images/{14.4_piseries .png => 14.4_piseries.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename images/{14.4_piseries .png => 14.4_piseries.png} (100%) diff --git a/images/14.4_piseries .png b/images/14.4_piseries.png similarity index 100% rename from images/14.4_piseries .png rename to images/14.4_piseries.png From abb36a01a498895610d014639d698ab90cf39dd1 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Tue, 29 Dec 2015 23:02:38 +0800 Subject: [PATCH 14/20] Update 14.4.md --- eBook/14.4.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/eBook/14.4.md b/eBook/14.4.md index 01180d5..17b309a 100644 --- a/eBook/14.4.md +++ b/eBook/14.4.md @@ -114,7 +114,29 @@ Received on channel 1: 94348 练习14.10:[polar_to_cartesian.go](exercises/chapter_14/polar_to_cartesian.go) -(这是一种综合练习,使用到章节4,9,11的内容和本章内容。) +(这是一种综合练习,使用到章节4,9,11的内容和本章内容。)写一个可交互的控制台程序,要求用户输入二位平面极坐标上的点(半径和角度(度))。计算对应的笛卡尔坐标系的点的x和y并输出。使用极坐标和笛卡尔坐标的结构体。 + +使用通道和协程: + `channel1`用来接收极坐标 + `channel2`用来接收笛卡尔坐标 + +转换过程需要在协程中进行,从channel1中读取然后发哦送到channel2。实际上做这种计算不提倡使用协程和通道,但是如果运算量很大很耗时,这种方案设计就非常合适了。 + + +练习14.11: [concurrent_pi.go](exercises/chapter_14/concurrent_pi.go) / [concurrent_pi2.go](exercises/chapter_14/concurrent_pi2.go) + +使用以下序列在协程中计算pi:开启一个协程来计算公式中的每一项并将结果放入通道,`main()`函数收集并累加结果,打印出pi的近似值。 + +![](../images/14.4_piseries.png?raw=true) + +计算执行时间(参见章节[6.11](6.11.md)) + +再次声明这只是为了一边练习协程的概念一边找点乐子。 + +如果你需要的话可使用`math.pi`中的Pi;而且不使用协程会运算的更快。一个急速版本:使用`GOMAXPROCS`,开启和`GOMAXPROCS`同样多个协程。 + +习惯用法:后台服务模式 + ## 链接 From a6aec5bed0302e2477a9bfada26b4fefea1d89ca Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 30 Dec 2015 17:31:42 +0800 Subject: [PATCH 15/20] =?UTF-8?q?=E5=AE=8C=E6=88=9014.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/14.4.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/eBook/14.4.md b/eBook/14.4.md index 17b309a..392b290 100644 --- a/eBook/14.4.md +++ b/eBook/14.4.md @@ -137,7 +137,38 @@ Received on channel 1: 94348 习惯用法:后台服务模式 +服务通常是是用后台协程中的无限循环实现的,在循环中使用`select`获取并处理通道中的数据: +```go +// Backend goroutine. +func backend() { + for { + select { + case cmd := <-ch1: + // Handle ... + case cmd := <-ch2: + ... + case cmd := <-chStop: + // stop server + } + } +} +``` +在程序的其他地方给通道`ch1`,`ch2`发送数据,比如:通道`stop`用来清理结束服务程序。 +另一种方式(但是不太灵活)就是(客户端)在`chRequest`上提交请求,后台协程循环这个通道,使用`switch`根据请求的行为来分别处理: +```go +func backent() { + for req := range chRequest { + switch req.Subjext() { + case A1: // Handle case ... + case A2: // Handle case ... + default: + // Handle illegal request .. + // ... + } + } +} +``` ## 链接 From c5b08a6803ca01ed0f25876217857bd426c5675d Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 30 Dec 2015 22:18:35 +0800 Subject: [PATCH 16/20] =?UTF-8?q?=E5=A2=9E=E5=8A=A014.4=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/directory.md | 1 + 1 file changed, 1 insertion(+) diff --git a/eBook/directory.md b/eBook/directory.md index eac2c1d..70eccbf 100644 --- a/eBook/directory.md +++ b/eBook/directory.md @@ -139,6 +139,7 @@ - 14.1 [并发,并行和协程](14.1.md) - 14.2 [使用通道进行协程间通信](14.2.md) - 14.3 [协程同步:关闭通道-对阻塞的通道进行测试](14.3.md) + - 14.4 [使用select切换协程](14.4.md) - 第15章:[网络、模版与网页应用](15.0.md) - 15.1 [tcp服务器](15.1.md) - 15.2 [一个简单的web服务器](15.2.md) From 8fa06effe24b6cc50f71feb52b40ce61a2e49230 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 30 Dec 2015 22:22:15 +0800 Subject: [PATCH 17/20] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=BB=83=E4=B9=A014.7?= =?UTF-8?q?=E7=9A=84goroutine=5Fclose=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eBook/14.4.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eBook/14.4.md b/eBook/14.4.md index 392b290..4b641a7 100644 --- a/eBook/14.4.md +++ b/eBook/14.4.md @@ -90,7 +90,7 @@ Received on channel 1: 94348 练习14.7: * a)在练习5.4的for_loop.go中,有一个常见的for循环打印数字。在函数`tel`中实现一个for循环,用协程开始这个函数并在其中给通道发送数字。`main()`线程从通道中获取并打印。不要使用`time.Sleep()`来同步:[goroutine_panic.go](exercises/chapter_14/goroutine_panic.go) -* b)也许你的方案有效,可能会引发运行时的panic:`throw:all goroutines are asleep-deadlock!` 为什么会这样?你如何解决这个问题?[goroutine_close.go]((exercises/chapter_14/goroutine_close.go)) +* b)也许你的方案有效,可能会引发运行时的panic:`throw:all goroutines are asleep-deadlock!` 为什么会这样?你如何解决这个问题?[goroutine_close.go](exercises/chapter_14/goroutine_close.go) * c)解决a)的另外一种方式:使用一个额外的通道传递给协程,然后在结束的时候随便放点什么进去。`main()`线程检查是否有数据发送给了这个通道,如果有就停止:[goroutine_select.go](exercises/chapter_14/goroutine_select.go) From 4e18e9fc6223949809c8d2d83952bc31bd9c8f55 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 30 Dec 2015 22:34:35 +0800 Subject: [PATCH 18/20] Update 14.3.md --- eBook/14.3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eBook/14.3.md b/eBook/14.3.md index 632f25d..cd70a9f 100644 --- a/eBook/14.3.md +++ b/eBook/14.3.md @@ -1,4 +1,4 @@ -# 14.3 协程的同步:关闭通道-测试阻塞的通道 +# 14.4 协程的同步:关闭通道-测试阻塞的通道 通道可以被显示的关闭;尽管它们和文件不同:不必每次都关闭。只有在当需要告诉接收者不会再提供新的值的时候,才需要关闭通道。只有发送者需要关闭通道,接收者永远不会需要。 From db3499ddbce83a65dcaa97b816ff50e7cbd17014 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 30 Dec 2015 22:34:57 +0800 Subject: [PATCH 19/20] Update 14.3.md --- eBook/14.3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eBook/14.3.md b/eBook/14.3.md index cd70a9f..632f25d 100644 --- a/eBook/14.3.md +++ b/eBook/14.3.md @@ -1,4 +1,4 @@ -# 14.4 协程的同步:关闭通道-测试阻塞的通道 +# 14.3 协程的同步:关闭通道-测试阻塞的通道 通道可以被显示的关闭;尽管它们和文件不同:不必每次都关闭。只有在当需要告诉接收者不会再提供新的值的时候,才需要关闭通道。只有发送者需要关闭通道,接收者永远不会需要。 From 70ab9c8d470bbcbee1d235f955564923b12ab397 Mon Sep 17 00:00:00 2001 From: glight2000 <173959153@qq.com> Date: Wed, 30 Dec 2015 23:01:37 +0800 Subject: [PATCH 20/20] Create 14.5.md --- eBook/14.5.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 eBook/14.5.md diff --git a/eBook/14.5.md b/eBook/14.5.md new file mode 100644 index 0000000..b01c8a3 --- /dev/null +++ b/eBook/14.5.md @@ -0,0 +1,51 @@ +# 14.5 通道,超时和计时器 + +`time`包中有一些有趣的功能可以和通道组合使用。 + +其中就包含了`time.Ticker`结构体,这个对象以指定的时间间隔重复的向通道C发送时间值: +```go +type Ticker struct { + C <-chan Time // the channel on which the ticks are delivered. + // contains filtered or unexported fields + ... +} +``` +时间间隔的单位是ns(纳秒,int64),在工厂函数`time.NewTicker`中以`Duration`类型的参数传入:`func Newticker(dur) *Ticker` + +在协程周期性的执行一些事情(打印状态日志,输出,计算等等)的时候非常有用。 + +调用`Stop()`使计时器停止,在`defer`语句中使用。这些都很好的适应`select`语句: +```go +ticker := time.NewTicker(updateInterval) +defer ticker.Stop() +... +select { +case u:= <-ch1: + ... +case v:= <-ch2: + ... +case <-ticker.C: + logState(status) // call some logging function logState +default: // no value ready to be received + ... +} +``` +`time.Tick()`函数声明为`Tick(d Duration) <-chan Time`,当你想返回一个通道而不必关闭它的时候这个函数非常有用:它以d为周期给返回的通道发送时间,d是纳秒数。如果需要像下边的代码一样,限制处理频率(函数`client.Call()`是一个RPC调用,这里暂不赘述(参见章节[15.9](15.9.md))): + +```go +import "time" + +rate_per_sec := 10 +var dur Duration = 1e9 / rate_per_sec +chRate := time.Tick(dur) // a tick every 1/10th of a second +for req := range requests { + <- chRate // rate limit our Service.Method RPC calls + go client.Call("Service.Method", req, ...) +} +``` + +## 链接 + +- [目录](directory.md) +- 上一节:[使用select切换协程](14.4.md) +- 下一节:[对协程使用recover](14.6.md)