Skip to content

Commit

Permalink
Merge pull request #160 from LinPr/master
Browse files Browse the repository at this point in the history
Golang Tip #32: Scheduling functions after context cancellation with context.AfterFunc
  • Loading branch information
smallnest authored Apr 26, 2024
2 parents 57ea599 + 138cd3e commit 50fca65
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Go tips from [Phuong Le](https://twitter.com/func25).
| 29 | Avoid context.Background(), make your goroutines promisable. | stonemax |
| 30 | 使用context.WithoutCancel()继续上下文操作 | smallnest |
| 31 | Loop labels for cleaner breaks and continues | zhubiaook |
| 32 | 已认领 | |
| 32 | Scheduling functions after context cancellation with context.AfterFunc | LinPr |
| 33 | Just... Don’t Panic() | baxiang |
| 34 | Lead with context, end with options, and always close with an error | lylex |
| 35 | Prefer strconv over fmt for converting to/from string | jjjjjim |
Expand Down
41 changes: 41 additions & 0 deletions src/032.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
> 原始链接: [Golang Tip #32: Scheduling functions after context cancellation with context.AfterFunc](https://twitter.com/func25/status/1762087461839364445)


在 tip #30,我们已经知道如何在父 context 停止的时候让 context 继续下去 :https://twitter.com/func25/status/1761388781201174853

现在让我看看在 Go1.21 引入的新特性

`context.AfterFunc` 可以让你设置一个回调函数 `f`,回调函数会在 `ctx` 结束后在它的上下文运行(无论是因为 `ctx` 被取消或者是超时)

![](./images/032/1.png)

该功能非常适合清理、记录日志或其类型的回收资源任务。

*回调函数什么时候执行?*

回调函数在一个新的 goroutine 中运行,该 goroutine 会在收到父 context 的 `ctx.done` 通道发出的信号后被触发

*如果 context 已经被取消了会发生什么?*

回调函数会立刻执行,当然这发生在 go 协程里

这里有几个关键点:

- 独立运行:,你可以在同一上下文中多次使用 AfterFunc 而不会出现任何问题,设置的每个任务都会独立运行。
- context结束时立刻执行:当你调用 AfterFunc 时,context被取消,它会在一个新的 go 协程中运行。
- 你可以取消计划中的函数,提供了一种结束机制(stop)可以结束运行中的回调函数
- 非阻塞:使用stop机制并不会等待回调函数结束,如果你希望主程序同步等待回调函数结束,你需要自己实现这个逻辑

我们来简单说下结束机制 `stop()`,它是 `AfterFunc` 的返回值

![](./images/032/2.png)

如果我们在上context 结束之前调用 stop(),而此时回调尚未运行(因此实际上,goroutine 尚未被触发),则 stopped 的值将为 true

这意味着我们成功阻止了回调函数的运行。

如果 stopped 的值为false,这可能意味着其中之一:

- 回调函数启动了一个协程正在运行中
- 回调函数已经被停止了
Binary file added src/images/032/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/032/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 50fca65

Please sign in to comment.