ProgrammingBackend Developer

What are receiver methods in Go, how are they implemented, and why is it important to distinguish them by type (value vs pointer)?

Pass interviews with Hintsage AI assistant

Answer.

Background: Receiver methods were introduced in Go to allow the implementation of interfaces and provide encapsulation of behavior for custom types, similar to class methods in OOP languages.

The Problem: In Go, methods can be declared for a struct (or other types) in two ways: via value receiver or pointer receiver. Incorrect application of their differences can lead to non-obvious errors, as behavior depends on how the method is declared and how it is called (via variable or pointer).

The Solution:

A method with a value receiver copies the entire struct upon invocation, and changes made inside such a method do not affect the original object. A pointer receiver allows manipulation of the original object and making changes. Choosing the correct receiver is important for performance optimization and correct behavior.

Code example:

package main import "fmt" type Counter struct { Value int } func (c Counter) IncByValue() { // value receiver c.Value++ } func (c *Counter) IncByPointer() { // pointer receiver c.Value++ } func main() { c := Counter{} c.IncByValue() fmt.Println(c.Value) // Will print 0 c.IncByPointer() fmt.Println(c.Value) // Will print 1 }

Key features:

  • Passing by value copies the object completely, changes are local.
  • Passing by pointer allows changing the struct field externally (visible in the calling code).
  • Methods with pointer receivers can be called both via variable and via pointer, Go will perform automatic conversion.

Trick Questions.

1. If a struct contains large fields (e.g., an array of [1000]int), which receiver is better to use for a method and why?

Answer: It is better to use a pointer receiver to avoid the cost of copying a large amount of data. A method with a value receiver will copy the entire object, which is inefficient.

2. Is a struct with a pointer receiver compatible with an interface that defines methods with a value receiver?

Answer: No. If the interface method is declared on a value, and the struct implements it only on a pointer — the compiler will not consider it compatible.

3. Can a method with a pointer receiver be called on a value variable (rather than on a pointer)?

Answer: Yes. Go implicitly takes the address (&struct), meaning the method will be invoked correctly.

c := Counter{} c.IncByPointer() // Go will call (&c).IncByPointer()

Common Mistakes and Anti-Patterns

  • Declaring a method on a value when it is necessary to modify the struct.
  • Interface implementation errors due to differences in receivers.
  • Inefficiency due to unnecessary copying of large structs.

Real-Life Example

Negative Case

In a project, the struct is huge, but all methods are declared on the value (value receiver). Every call copies the entire object, which significantly impacts performance.

Pros: Simplicity, impossible to accidentally change the original object. Cons: High memory and CPU costs.

Positive Case

For a small struct without much state, methods are declared on value; for large ones — only on pointers. Methods that modify the object use pointers.

Pros: Memory savings, correct state modification. Cons: Need to keep track of interface compatibility and remember pointer passing specifics.