Skip to content

Commit

Permalink
Merge pull request #115 from QingyaFan/master
Browse files Browse the repository at this point in the history
add tips 21: Prefer using a pointer receiver when defining methods
  • Loading branch information
smallnest authored Apr 23, 2024
2 parents 3f7a136 + 491f8dc commit 4bbc521
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 3 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ Go tips from [Phuong Le](https://twitter.com/func25).
| 17 | | |
| 18 | | |
| 19 | | |
| 20 | Pass values, not pointers | smallnest |
| 21 | | |
| 22 | Simplify function signatures with structs or variadic options | zhubiaook |
| 20 | Pass values, not pointers | smallnest |
| 21 | Prefer using a pointer receiver when defining methods | QingyaFan |
| 22 | | |
| 23 | Skip the 'Get' prefix for getters | HBUzxl |
| 24 | | |
| 25 | | |
Expand Down
43 changes: 43 additions & 0 deletions src/021.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Golang Tip #21: 定义方法时,优先使用指针作为接收器(receiver)

> 原文链接:[Golang Tip #21: Prefer using a pointer receiver when defining methods.](https://twitter.com/func25/status/1758085077211443304)
>
在继续之前,这里有一个关于指针接收器与值接收器的简短介绍:https://twitter.com/func25/status/1757759982354026636

在Go中,规则并非是非黑即白的:“使用指针接收器进行修改,否则使用值接收器”。

一些指导原则:

何时选择指针接收器?

- 修改接收器的状态时
- 对于被认为是“大型”的结构体。这可能有点主观,就像我之前的推文中提到的那样
- 当结构体包含同步字段时,例如sync.Mutex,选择指针可以避免复制锁

![tips21-img01](./images/021/tips21-img01.png)

- 如果不确定,选择指针接收器是比较明智的选择

何时适合使用值接收器?

- 小型且不会被改变的类型
- 如果你的类型是 map、func、channel,或者涉及到切片,而且切片的大小和容量不会改变(尽管元素可能会改变)

> “为什么切片的大小和容量不会被改变?”
尽管你可以通过值接收器修改切片的元素或底层数组的内容(影响原始切片),但调整切片的大小(例如,使用append来增加容量)不会影响方法外部的原始切片。

这里有一个例子:
https://twitter.com/func25/status/1731181436282208375

最后,一致性至关重要。

避免在给定结构体中混合使用不同的接收器类型,以保持一致性。

如果任何方法因为需要进行修改而使用指针接收器,通常最好为该结构体的所有方法都使用指针接收器,即使其中一些方法并不会引起修改。

我想到的主要理由有:

- 混合使用两种接收器可能会导致对该结构体进行操作时出现混乱和不一致,尤其是在更改接收器类型时
- 为了保持对象与接口的交互一致和简单(更多详情,参考我之前在 4/4 部分的推文)
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- [Tip #14 错误信息不要大写或者以标点结尾](./014.md)
- [Tip #16 不要通过返回 -1 或者 nil 来表示错误](./016.md)
- [Tip #20 传递值,而不是指针](./020.md)
- [Tip #21 定义方法时,优先使用指针作为接收器](./021.md)
- [Tip #22 使用结构体或变长参数简化函数签名](./022.md)
- [Tip #23 省略 getter 方法的'Get'前缀](./023.md)
- [Tip #27 原地过滤](./027.md)
Expand Down
Binary file added src/images/021/tips21-img01.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 4bbc521

Please sign in to comment.