Go 指针和值接收器类型之间的区别是什么?

Go 指针和值接收器类型之间的区别是什么?,go,Go,我正在编写一个程序,从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.decryp

我正在编写一个程序,从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...*/}

现在我的代码神奇地工作了。发生了什么?

值接收器对
SecureReader
实例
s
的副本进行操作

如果该方法对实例副本的任何部分进行变异(如modify
s.decrypted
),则一旦该方法退出,它在接收方的原始实例上就不可见

随着指针接收器的变化,这种情况会发生变化,因为指针的副本被传递给该方法,因此该方法在该接收器中运行,并且可以改变实际的
SecureReader
实例
s


请参阅“”中的更多示例

简单地说:您可以将接收方视为传递给方法的参数。您可能希望按值传递或按引用传递的所有相同原因都适用

您希望通过引用而不是通过值传递的原因:

  • 您希望实际修改接收器(“读/写”而不是“读”)
  • 该结构非常大,而且深度副本非常昂贵
  • 一致性:如果结构上的某些方法具有指针接收器,则其他方法也应具有指针接收器。这允许行为的可预测性
如果在方法调用中需要这些特性,请使用指针接收器


这是否意味着每次调用Read()时都会传入一个新的SecureReader?为什么io.Reader会施加这样一个尴尬的限制?@SomeNoobStudent接口包含一个指向数据的指针,所以复制接口不是什么大问题。另一方面,复制一个结构是,因为它防止了可变性!多么有启发性啊!非常感谢你!给你大量的投票。有些方法可能有一个引用作为接收者,而另一些方法可能有一个实例吗?我的意思是,如果我需要一个结构来实现某个接口,那么一些方法可能是“读”的,而另一些方法可能是“写”的。如果这是不可能的,拥有实例方法将看起来像一个非常奇怪的语言特性。我认为这在技术上是可能的,但一致性是关键。