在go中,值接收者操作的是结构体的副本,对字段(如`bytes.buffer`)的修改不会影响原始实例;而指针接收者直接操作原结构体,可持久化状态变更——这是解决“方法看似执行却无效果”问题的关键。
在你的 SecureReader 示例中,问题根源在于接收者类型的选择:
func (s SecureReader) Read(b []byte) (int, error) {
s.decryptPipeIntoBuffer() // ← 此处调用的是值接收者版本
return s.decrypted.Read(b)
}
当 decryptPipeIntoBuffer() 使用 值接收者(func (s SecureReader) decryptPipeIntoBuffer())时,Go 会将整个 SecureReader 实例(含 decrypted bytes.Buffer 字段)复制一份传入方法。即使该方法内部向 s.decrypted 写入了数据,这些写入仅发生在副本上;方法返回后,副本被销毁,原始 SecureReader 的 decrypted 缓冲区仍为空——因此后续 s.decrypted.Read(b) 立即返回 io.EOF。
而改为 指针接收者 后:
func (s *SecureReader) decryptPipeIntoBuffer() (int, error) {
// s 是指向原始实例的指针
// s.decrypted.Write(...) 将真实修改原始缓冲区
}
此时 s 指向原始 SecureReader 实例,所有对 s.decrypted 的操作(如 Write, WriteString, Grow 等)都会直接影响原始字段,确保状态被正确缓存和复用。