Skip to content

Commit

Permalink
翻译成通顺的中文
Browse files Browse the repository at this point in the history
  • Loading branch information
smallnest committed Apr 27, 2024
1 parent 3822b7c commit 17b11d2
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 37 deletions.
4 changes: 2 additions & 2 deletions 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 | Scheduling functions after context cancellation with context.AfterFunc | LinPr |
| 32 | Scheduling functions after context cancellation with context.AfterFunc | LinPr,smallnest |
| 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 All @@ -95,7 +95,7 @@ Go tips from [Phuong Le](https://twitter.com/func25).
| 40 | Handle errors while using defer to prevent silent failures | smallnest |
| 41 | Sort your fields in your struct from largest to smallest | justlorain |
| 42 | Single Touch Error Handling, Less Noise. | zhubiaook |
| 43 | Gracefully Shut Down Your Application | LinPr |
| 43 | Gracefully Shut Down Your Application | LinPr,smallnest |
| 44 | Intentionally Stop with Must Functions | syjs10 |
| 45 | Always Manage Your Goroutine Lifetime. | stonemax |
| 46 | Avoid using break in switch cases, except when paired with labels | baxiang |
Expand Down
43 changes: 22 additions & 21 deletions src/032.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
# Tip #31 使用跳转标签让break和continue语句更简洁

> 原始链接: [Golang Tip #32: Scheduling functions after context cancellation with context.AfterFunc](https://twitter.com/func25/status/1762087461839364445)
>
[tip #30](https://colobu.com/gotips/030.html),我们学习了如何使一个Context在其Context停止时仍能继续运行:

现在,让我们来看一下Go 1.21引入的一项新特性。

在 tip #30,我们已经知道如何在父 context 停止的时候让 context 继续下去 :https://twitter.com/func25/status/1761388781201174853
`context.AfterFunc`允许您设置一个回调函数`f`,在ctx结束后(无论因取消还是超时)在新的goroutine中运行。

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

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

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

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

*回调函数什么时候执行?*
该特性对于清理、日志记录或其他取消后的任务非常有用。

回调函数在一个新的 goroutine 中运行,该 goroutine 会在收到父 context 的 `ctx.done` 通道发出的信号后被触发
> “回调函数何时运行?”
*如果 context 已经被取消了会发生什么?*
回调函数在一个新的goroutine中运行,该goroutine在接收到父级上下文的ctx.done通道发送的信号后被触发。

回调函数会立刻执行,当然这发生在 go 协程里
> “如果上下文已经取消了怎么办?”
这里有几个关键点:
回调函数会立即运行,当然也是在一个新的`goroutine`中。

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

我们来简单说下结束机制 `stop()`,它是 `AfterFunc` 的返回值
- 自行运行:您可以多次使用同一上下文调用`AfterFunc`而没有任何问题,您设置的每个任务都会各自独立运行。
- 如果上下文已完成则立即运行:如果在调用`AfterFunc``ctx`已结束,则它会立即在一个新的goroutine中启动`f`
- 可以取消计划中的函数:它为您提供了一个`stop`函数,可以阻止f运行。
- 非阻塞:使用`stop`不会等待f完成,而是快速停止。如果您需要f和主线程工作保持同步,需要您自行安排。
接下来我们谈谈AfterFunc返回的stop()函数:

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

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

这意味着我们成功阻止了回调函数的运行。
如果我们尚未完成上下文且回调尚未运行(实际上,goroutine尚未被触发)时就调用stop(),那么stopped将为true。

如果 stopped 的值为false,这可能意味着其中之一:
这意味着我们成功阻止了回调的运行。

- 回调函数启动了一个协程正在运行中
- 回调函数已经被停止了
如果stop()返回false,则可能意味着:
- 函数f已在新的goroutine中开始运行。
- 函数`f`已被停止。
27 changes: 13 additions & 14 deletions src/043.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,26 @@

> 原始连接:[Golang Tip #43: Gracefully Shut Down Your Application ](https://twitter.com/func25/status/1766104130303705226)
当我们讨论优雅地关闭一个应用程序的时候,这里会有几件关键目标我们需要保证
当我们讨论优雅地关闭应用程序时,有几个关键保证是我们力求实现的

- 没有新的请求:服务端停止接收新的请求
- 运行中任务的完成:等待当前运行中的任务到逻辑上的停止点
- 资源的清理:释放比如数据库连接,打开的文件,网络连接等资源
- 不接收新请求:服务器停止接受新的请求。
- 完成正在进行的任务:等待当前处理的任务达到逻辑上的停止点。
- 资源清理:释放诸如数据库连接、打开文件、网络连接等资源

有一些不同的实现方法,但为了简单起见,我尽量给出最简洁的方法
虽然存在一些不同的实现方式,但为了简化起见,我尝试给出最简短的方法
![](./images/043/1.png)

首先,我们创建一个(主)上下文,当接收到中断信号(`Ctrl+C`)或`SIGTERM`时将其取消。

首先,我们创建一个(main)上下文,当收到中断信号`(Ctrl+C)``SIGTERM` 时,该上下文将被取消(canceled)。
接着我们创建两个goroutine,均由`errgroup`协调(如果您还不了解它,请考虑阅读 https://blog.devtrovert.com/p/go-errgroup-you-havent-used-goroutines):

然后我们创建了两个 go 协程,他们都由 `errgroup` 来管理(如果你不知道 `errgroup` 是什么,可以参考 [Go Errgroup: How to Use Goroutines Effectively (devtrovert.com)](https://blog.devtrovert.com/p/go-errgroup-you-havent-used-goroutines)
第一个直接启动服务器,但要记住,`ListenAndServe` 始终返回非空错误。
第二个更有趣,这是我们放置优雅清理代码的地方。这个goroutine等待`gCtx.Done()`关闭,该关闭状态由我们的主ctx传播而来。

+ 第一个 go 协程很直观,启动一个 server,但是要记住 `ListenAndServe` 函数总是返回非空`(non-nil)`的 error
+ 第二个 go 协程很有意思,在这个协程中我们可以做优雅清理。这个协程等待`gCtx.Done() `关闭,这个关闭事件是从主上下文`(main ctx)`中传递过来的。
如果您的服务运行在Kubernetes上,应考虑在接收到SIGTERM后不立即终止新请求。

如果我们的服务运行在 Kubernetes 上,考虑不要在收到新的 `SIGTERM` 信号之后立即终止新请求
您的应用程序不应立即终止,而应完成所有活跃请求,并继续监听Pod关闭开始后到达的传入连接

您的应用程序不能立即终止,而是要继续完成所有活跃的请求,并且继续监听 Pod 关闭开始后到达的连接
Kubernetes可能需要一段时间来更新所有kube-proxy和负载均衡器

Kubernetes 更新所有 kube-proxies 和负载均衡器可能需要一些时间。

这是简化版本,您可以考虑在服务器配置中添加超时时间,检查错误是否已关闭,在关闭 server 上添加超时 ......
这是简化版,您可能需要考虑为服务器配置添加超时、检查错误是否关闭、为关闭过程添加超时等。
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
- [Tip #29 避免使用 context.Background,使你的协程具备承诺性](./029.md)
- [Tip #30 使用context.WithoutCancel()继续上下文操作](./030.md)
- [Tip #31 使用跳转标签让break和continue语句更简洁](./031.md)
- [Tip #32 使用跳转标签让break和continue语句更简洁](./032.md)
- [Tip #33 尽量...不要使用panic()](./033.md)
- [Tip #34 以context开头,以options结尾,并且总是用error来关闭](./034.md)
- [Tip #35 转换字符串时优先使用 strconv 而非 fmt](./035.md)
Expand Down

0 comments on commit 17b11d2

Please sign in to comment.