Receivers and Interfaces

Methods with value receivers can be called on pointers as well as values.

For example,

  1. type S struct {
  2. data string
  3. }
  4.  
  5. func (s S) Read() string {
  6. return s.data
  7. }
  8.  
  9. func (s *S) Write(str string) {
  10. s.data = str
  11. }
  12.  
  13. sVals := map[int]S{1: {"A"}}
  14.  
  15. // You can only call Read using a value
  16. sVals[1].Read()
  17.  
  18. // This will not compile:
  19. // sVals[1].Write("test")
  20.  
  21. sPtrs := map[int]*S{1: {"A"}}
  22.  
  23. // You can call both Read and Write using a pointer
  24. sPtrs[1].Read()
  25. sPtrs[1].Write("test")

Similarly, an interface can be satisfied by a pointer, even if the method has avalue receiver.

  1. type F interface {
  2. f()
  3. }
  4.  
  5. type S1 struct{}
  6.  
  7. func (s S1) f() {}
  8.  
  9. type S2 struct{}
  10.  
  11. func (s *S2) f() {}
  12.  
  13. s1Val := S1{}
  14. s1Ptr := &S1{}
  15. s2Val := S2{}
  16. s2Ptr := &S2{}
  17.  
  18. var i F
  19. i = s1Val
  20. i = s1Ptr
  21. i = s2Ptr
  22.  
  23. // The following doesn't compile, since s2Val is a value, and there is no value receiver for f.
  24. // i = s2Val

Effective Go has a good write up on Pointers vs. Values.