2015-04-05 107 views
2

我正在寫一個程序,它從一個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...*/} 

現在我的代碼可以神奇地運行。到底是怎麼回事?

回答

2

值接收器操作副本SecureReader實例s

如果方法變異的實例副本任何部分(如修改s.decrypted),它是不可見的接收器上的原始實例,一旦方法退出。

即用指針接收器,其中,該方法進行操作,並且可以變異的實際SecureReader實例s改變,由於複製指針的被傳遞給該方法。


查看「Don't Get Bitten by Pointer vs Non-Pointer Method Receivers in Golang」中的更多示例。

簡單地說:你可以把接收者看作是傳遞給方法的參數。所有相同的原因爲什麼你可能想通過價值或通過參考適用。

原因,你會希望通過引用傳遞由值反對:

  • 要真正地修改接收器(「讀/寫」,而不是僅僅「讀」)
  • 的結構非常大,並且深度副本很昂貴
  • 一致性:如果結構中的某些方法具有指針接收器,則其餘部分也應該如此。這允許行爲的可預測性

如果在方法調用中需要這些特性,請使用指針接收器。

+0

這是否意味着每次我調用Read()時都會傳入一個新的SecureReader?爲什麼io.Reader會施加如此尷尬的限制? – 2015-04-05 22:10:08

+1

@SomeNoobStudent一個接口包含一個指向數據的指針,所以複製一個接口並不是什麼大問題。另一方面,複製結構是因爲它阻止了可變性。 – VonC 2015-04-05 22:17:32

+0

哦!多麼啓發!非常感謝!用upvotes淋浴你。 – 2015-04-05 22:20:51

相關問題