Skip to content

Commit

Permalink
Merge pull request #138 from vcheckzen/master
Browse files Browse the repository at this point in the history
Add tip 048 and 049
  • Loading branch information
smallnest authored Apr 24, 2024
2 parents f631fbc + 165e5bd commit 2489aa6
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ Go tips from [Phuong Le](https://twitter.com/func25).
| 45 | Always Manage Your Goroutine Lifetime. | stonemax |
| 46 | Avoid using break in switch cases, except when paired with labels | baxiang |
| 47 | Table-driven tests, subtests, and parallel tests | devin7788 |
| 48 | | |
| 49 | | |
| 48 | Avoid Global Variables, Especially Mutable Ones. | vcheckzen |
| 49 | Give the Caller the Right to Make Decisions | vcheckzen |
| 50 | Make Structs Non-comparable. | smallnest |
| 51 | | |
| 52 | Adjusting GOMAXPROCS for Containerized Env (Kubernetes, Docker, etc.) | baxiang |
Expand Down
35 changes: 35 additions & 0 deletions src/048.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Tip #48 避免使用全局变量,尤其是可变变量

> 原始链接:[Golang Tip #48: Avoid Global Variables, Especially Mutable Ones.](https://twitter.com/func25/status/1767903551303586048)
**全局变量**是我们放在函数或方法之外的变量,可供我们代码的任何部分使用和更改。

![001](./images/048/001.png)

现在,我并不是说所有全局变量都是坏消息,但它们带来的麻烦往往大于其价值。

原因如下(使用上面的代码示例):

- **难以跟踪变化**:当代码的任何部分都可以改变 `featureConfig.NewCheckoutProcessEnabled` 时,识别它被改变的位置会很困难。
- **测试变得棘手**:假设您正在测试新旧结帐流程。如果两个测试都涉及相同的全局 `featureConfig`,则您无法**独立**测试它们,因为其中一个测试会干扰另一个测试。
- **并发问题**:当多个请求同时尝试读取或更改 `featureConfig` 时,可能会导致不一致(竞态条件)。

> “那么,解决方案是什么?”
**答案是依赖注入。**

这是一种从外部满足对象需求的方法,而不是让它自己创建或从全局变量获取:

![002](./images/048/002.png)

是的,这种方法确实使事情变得有点复杂,但它也使得维护代码、测试代码和查找错误变得容易得多。

通过依赖注入,测试启用和禁用功能这两种场景变得非常简单:

![003](./images/048/003.png)

但是如果您的全局变量不会改变,不需要测试并且必须这样工作,那么在这些情况下坚持使用全局变量可能会更好。

此外,如果您使用在运行时发生变化的全局变量,请确保使用同步技术(如互斥锁)来保证顺序。

简而言之,从全局状态转移到依赖注入可以让您的代码保持灵活性,并且不会过度依赖或紧密 “耦合”。
56 changes: 56 additions & 0 deletions src/049.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Tip #49:赋予调用者决策权

> 原始链接:[Golang Tip #49: Give the Caller the Right to Make Decisions.](https://twitter.com/func25/status/1768270595521929430)
想法是这样的:当你编写函数或包时,你必须决定:

- 如何管理错误,是打印日志还是触发 panic?
- 创建 goroutine 是否合适?
- 将上下文超时设置为 10 秒是个好主意吗?

关键原则是允许代码的使用者(调用者)拥有做出这些选择的控制权和**职责**,而不是在你的代码中为他们做出决定。

让我们看一些例子。

## 1. 处理错误

这是一个记录错误并将其返回给调用者的示例:

![001](./images/049/001.png)

与其在你的函数里触发 panic 或打印错误,不如****将错误发送给调用者。

这种方法可以让调用者找到最佳的处置方案,可以是记录错误,再试一次,或者在情况确实无法恢复时触发 panic。

> “为什么不在我们的函数和调用者的函数里同时记录错误,以便更容易地追溯?”
这个想法与 [Tip #42:单次错误处理,减少噪音](./042.md) 相关。

大体来说,我们让调用者根据自己的情况来确定错误的严重程度。

## 2. Goroutines

我见过一些用来运行后台任务的函数,像下图这样:

![002](./images/049/002.png)

当函数需要执行并发操作时,我们倾向于启动一个 goroutine。

但是,通常让调用者决定何时以及如何处理并发会更好,`go fire ()`

上面的例子也缺乏控制,我们可能希望给予调用者权限来控制 goroutine 的生命周期。

## 3. 其他操作

这个原则不仅限于启动 goroutine 和错误处理,我之所以关注它们是因为它们与我们的语言密切相关。

它包括更多代码设计决策,它们都与允许调用者决定相关:

- 操作在超时前应等待多长时间
- 使用什么级别的日志记录
- 是否使用数据库事务
- 以及更多...

然而,就像软件开发中的许多技巧一样,一切都是权衡。你不会想用太多选项让调用者心智负担过重。

通过将关键决策交给调用者,您的代码将变得更具适应性、可重用性,并能够**适用不同的上下文**
2 changes: 2 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
- [Tip #45 始终管理您协程的生命周期](./045.md)
- [Tip #46 避免在 switch 语句的 case 中使用 break,除非与标签一起使用](./046.md)
- [Tip #47 表驱动测试,测试集和并行运行测试](./047.md)
- [Tip #48 避免使用全局变量,尤其是可变变量](./048.md)
- [Tip #49:赋予调用者决策权](./049.md)
- [Tip #50 使结构体不可比较](./050.md)
- [Tip #52 针对容器化环境(Kubernetes、Docker等)调整GOMAXPROCS](./052.md)
- [Tip #53 枚举从1开始用于分类,从0用于默认情况](./053.md)
Expand Down
Binary file added src/images/048/001.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/048/002.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/048/003.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/049/001.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/049/002.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 2489aa6

Please sign in to comment.