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.
2条回答 默认 最新
- duanre4421 2019-02-01 09:44关注
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) ", vt, vt.AbsPointer(), "pointer", "value") // call pointer method, with value, fmt.Printf("Abs of %v is %v. (Call %s method, with %s) ", 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) ", vt, vt.ScalePointer(10), "pointer", "value") // call pointer method, with value, fmt.Printf("%v scale by 10 is: %v (Call %s method, with %s) ", 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) ", vt, (&vt).AbsValue(), "value", "pointer") // call value method, with pointer, fmt.Printf("Abs of %v is %v. (Call %s method, with %s) ", vt, vt.AbsValue(), "value", "value") // call value method, with value, } func main() { // pointerCallerLearn() valueCallerLearn() }
Just modify
main()
, and run viago run method_test.go
, then check the output to see how it works.本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报 - If the value is addressable, (which is true for most data type in go).
悬赏问题
- ¥15 素材场景中光线烘焙后灯光失效
- ¥15 请教一下各位,为什么我这个没有实现模拟点击
- ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
- ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
- ¥20 有关区间dp的问题求解
- ¥15 多电路系统共用电源的串扰问题
- ¥15 slam rangenet++配置
- ¥15 有没有研究水声通信方面的帮我改俩matlab代码
- ¥15 ubuntu子系统密码忘记
- ¥15 保护模式-系统加载-段寄存器