I want to know whats the difference of having methods on pointer and method on values. How both the methods work on standard structure instance as well as structure pointer.
-
2Possible duplicate of [Value receiver vs. Pointer receiver in Golang?](https://stackoverflow.com/questions/27775376/value-receiver-vs-pointer-receiver-in-golang) – Jonathan Hall Feb 01 '19 at 10:38
2 Answers
Define receiver as value
Format:
func (r T) Xxx() {}
Could call by either a value or a pointer.
When call with pointer, the value will be passed automatically, (it actually use *
to get value of the caller, and pass it).
Define receiver as pointer
Format:
func (r *T) Xxx() {}
In principle, should invoke with pointer only, but that's not necessary.
Because when call with value, instead of pointer, compiler will take care of it, when possible:
- If the value is addressable, (which is true for most data type in go).
Then compiler will take the address (via&
), and pass it automatically.
This enable to call a pointer method with value directly, (this is pretty common in go I guess, and it makes programmer's life easier). - If the value is not addressable, (which is rare, but exists).
Then need to pass the address explicitly, otherwise would get error when compile.
e.gmap
's element is not addressable.
Tips
Pointer caller is preferred, when define a method, if proper.
Reasons:- It could modify the caller.
- It's more lightweight for a complex caller.
What is passed to method, depends on the method signature, not how you call it (this is similar as with param).
- When declare caller as pointer
(r *T)
, it pass pointer. - When declare caller as value
(r T)
, it pass a copy of original caller.
- When declare caller as pointer
T
itself can't be pointer.
Code
And, here is a go code that I wrote when learning this feature.
Its 2 functions called in main()
tests the 2 features respectively.
method_learn.go:
// method - test
package main
import (
"fmt"
"math"
)
type Vertex struct {
x float64
y float64
}
// abs, with pointer caller,
func (v *Vertex) AbsPointer() float64 {
return math.Sqrt(v.x*v.x + v.y*v.y)
}
// scale, with pointer caller,
func (v *Vertex) ScalePointer(f float64) *Vertex {
v.x = v.x * f
v.y = v.y * f
return v
}
// abs, with value caller,
func (v Vertex) AbsValue() float64 {
return math.Sqrt(v.x*v.x + v.y*v.y)
}
// test - method with pointer caller,
func pointerCallerLearn() {
vt := Vertex{3, 4}
fmt.Printf("Abs of %v is %v. (Call %s method, with %s)\n", vt, vt.AbsPointer(), "pointer", "value") // call pointer method, with value,
fmt.Printf("Abs of %v is %v. (Call %s method, with %s)\n\n", vt, (&vt).AbsPointer(), "pointer", "pointer") // call pointer method, with pointer,
// scala, change original caller,
fmt.Printf("%v scale by 10 is: %v (Call %s method, with %s)\n", vt, vt.ScalePointer(10), "pointer", "value") // call pointer method, with value,
fmt.Printf("%v scale by 10 is: %v (Call %s method, with %s)\n", vt, (&vt).ScalePointer(10), "pointer", "pointer") // call pointer method, with pointer,
}
// test - method with value caller,
func valueCallerLearn() {
vt := Vertex{3, 4}
fmt.Printf("Abs of %v is %v. (Call %s method, with %s)\n", vt, (&vt).AbsValue(), "value", "pointer") // call value method, with pointer,
fmt.Printf("Abs of %v is %v. (Call %s method, with %s)\n", vt, vt.AbsValue(), "value", "value") // call value method, with value,
}
func main() {
// pointerCallerLearn()
valueCallerLearn()
}
Just modify main()
, and run via go run method_test.go
, then check the output to see how it works.

- 22,183
- 20
- 145
- 196
The big difference between them is that value receivers are copied*. So if you want to mutate your receiver, you have to use pointer. Observe:
package main
import (
"fmt"
)
type Person struct {
Age int
}
func (p Person) GrowUp1() {
p.Age++
}
func (p *Person) GrowUp2() {
p.Age++
}
func main() {
p := Person{Age: 20}
fmt.Println(p)
p.GrowUp1()
fmt.Println(p)
p.GrowUp2()
fmt.Println(p)
}
// {20}
// {20}
// {21}
* Pointers are copied too, naturally. But since they're pointers, a copy of a pointer still points to the same object.

- 226,338
- 43
- 373
- 367