我正在编写一个程序,它从io.Reader读取数据并将它们缓存在bytes.Buffer中。
type SecureReader struct {
pipe io.Reader
shared *[32]byte
decrypted bytes.Buffer
}
func (s SecureReader) Read(b []byte) (int, error) {
s.decryptPipeIntoBuffer()
return s.decrypted.Read(b)
}
func (s SecureReader) decryptPipeIntoBuffer() (int, error) {/*Lots of code...*/}
我首先使用了值接收器,因为我认为它们是相同的。但是,我注意到我的方法在调用时没有做任何事情:SecureReader.Read()总是返回io.EOF。
我撞了一下头,将接收器类型更改为
func (s *SecureReader) decryptPipeIntoBuffer() (int, error) {/*Lots of code...*/}
现在我的代码神奇地工作了。发生了什么事?
答案 0 :(得分:3)
值接收器在SecureReader
实例s
的副本上运行。
如果方法改变了实例的 copy 的任何部分(如修改s.decrypted
),则一旦方法退出,它就不会在接收器的原始实例上可见。< / p>
使用指针接收器进行更改,该方法操作并可以改变实际的SecureReader
实例s
,因为指针的 copy 被传递给方法。
请参阅“Don't Get Bitten by Pointer vs Non-Pointer Method Receivers in Golang”中的更多示例。
简单地说:您可以将接收器视为传递给方法的参数。您可能希望通过值传递或通过引用传递的所有相同原因都适用。
您希望通过引用传递而不是按值传递的原因:
- 您想要实际修改接收器(“读/写”而不是“读”)
- 结构非常大,深拷贝很贵
- 一致性:如果struct上的某些方法有指针接收器,其余的也应该如此。这允许行为的可预测性
如果在方法调用中需要这些特性,请使用指针接收器。