diff --git a/README.md b/README.md index b76d146..832922c 100644 --- a/README.md +++ b/README.md @@ -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 | | | diff --git a/src/021.md b/src/021.md new file mode 100644 index 0000000..545a08f --- /dev/null +++ b/src/021.md @@ -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 部分的推文) \ No newline at end of file diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 3350a4c..5a4096d 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -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) diff --git a/src/images/021/tips21-img01.png b/src/images/021/tips21-img01.png new file mode 100644 index 0000000..81f4b3b Binary files /dev/null and b/src/images/021/tips21-img01.png differ