第十四章上半部分 (#836)

Co-authored-by: Joe Chen <jc@unknwon.io>
This commit is contained in:
Haigang Zhou
2022-05-17 16:24:13 +08:00
committed by GitHub
parent 92d91dfa1c
commit f08d76efa6
11 changed files with 112 additions and 114 deletions

View File

@@ -2,7 +2,7 @@
`time` 包中有一些有趣的功能可以和通道组合使用。
其中就包含了 `time.Ticker` 结构体,这个对象以指定的时间间隔重复的向通道 C 发送时间值:
其中就包含了 `time.Ticker` 结构体,这个对象以指定的时间间隔重复的向通道 `C` 发送时间值:
```go
type Ticker struct {
@@ -12,7 +12,7 @@ type Ticker struct {
}
```
时间间隔的单位是 ns纳秒int64在工厂函数 `time.NewTicker` 中以 `Duration` 类型的参数传入:`func NewTicker(dur) *Ticker`
时间间隔的单位是 `ns`(纳秒,`int64`),在工厂函数 `time.NewTicker` 中以 `Duration` 类型的参数传入:`func NewTicker(dur) *Ticker`
在协程周期性的执行一些事情(打印状态日志,输出,计算等等)的时候非常有用。
@@ -34,7 +34,7 @@ default: // no value ready to be received
}
```
`time.Tick()` 函数声明为 `Tick(d Duration) <-chan Time`,当你想返回一个通道而不必关闭它的时候这个函数非常有用:它以 d 为周期给返回的通道发送时间,d 是纳秒数。如果需要像下边的代码一样,限制处理频率(函数 `client.Call()` 是一个 RPC 调用,这里暂不赘述(参见第 [15.9](15.9.md) 节):
`time.Tick()` 函数声明为 `Tick(d Duration) <-chan Time`,当你想返回一个通道而不必关闭它的时候这个函数非常有用:它以 `d` 为周期给返回的通道发送时间,`d` 是纳秒数。如果需要像下边的代码一样,可以限制处理频率(函数 `client.Call()` 是一个 RPC 调用,这里暂不赘述(参见第 [15.9](15.9.md) 节)
```go
import "time"
@@ -52,7 +52,7 @@ for req := range requests {
问题 14.1:扩展上边的代码,思考如何承载周期请求数的暴增(提示:使用带缓冲通道和计时器对象)。
定时器Timer结构体看上去和计时器Ticker结构体的确很像(构造为 `NewTimer(d Duration)`),但是它只发送一次时间,在 `Dration d` 之后。
定时器 (`Timer`) 结构体看上去和计时器 (`Ticker`) 结构体的确很像(构造为 `NewTimer(d Duration)`),但是它只发送一次时间,在 `Dration d` 之后。
还有 `time.After(d)` 函数,声明如下:
@@ -111,7 +111,7 @@ tick.
BOOM!
```
习惯用法:简单超时模式
**习惯用法:简单超时模式**
要从通道 `ch` 中接收数据,但是最多等待 1 秒。先创建一个信号通道,然后启动一个 `lambda` 协程,协程在给通道发送数据之前是休眠的:
@@ -137,7 +137,7 @@ select {
第二种形式:取消耗时很长的同步调用
也可以使用 `time.After()` 函数替换 `timeout-channel`。可以在 `select` 中通过 `time.After()` 发送的超时信号来停止协程的执行。以下代码,在 `timeoutNs` 纳秒后执行 `select``timeout` 分支后,执行`client.Call` 的协程也随之结束,不会给通道 `ch` 返回值:
也可以使用 `time.After()` 函数替换 `timeout-channel`。可以在 `select` 中通过 `time.After()` 发送的超时信号来停止协程的执行。以下代码,在 `timeoutNs` 纳秒后执行 `select``timeout` 分支后,执行 `client.Call` 的协程也随之结束,不会给通道 `ch` 返回值:
```go
ch := make(chan error, 1)
@@ -151,7 +151,7 @@ case <-time.After(timeoutNs):
}
```
注意缓冲大小设置为 1 是必要的,可以避免协程死锁以及确保超时的通道可以被垃圾回收。此外,需要注意在有多个 `case` 符合条件时, `select``case` 的选择是伪随机的,如果上面的代码稍作修改如下,则 `select` 语句可能不会在定时器超时信号到来时立刻选中 `time.After(timeoutNs)` 对应的 `case`,因此协程可能不会严格按照定时器设置的时间结束。
注意缓冲大小设置为 `1` 是必要的,可以避免协程死锁以及确保超时的通道可以被垃圾回收。此外,需要注意在有多个 `case` 符合条件时, `select``case` 的选择是伪随机的,如果上面的代码稍作修改如下,则 `select` 语句可能不会在定时器超时信号到来时立刻选中 `time.After(timeoutNs)` 对应的 `case`,因此协程可能不会严格按照定时器设置的时间结束。
```go
ch := make(chan int, 1)