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 数学建模招标中位数问题
- ¥15 phython路径名过长报错 不知道什么问题
- ¥15 深度学习中模型转换该怎么实现
- ¥15 HLs设计手写数字识别程序编译通不过
- ¥15 Stata外部命令安装问题求帮助!
- ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
- ¥15 TYPCE母转母,插入认方向
- ¥15 如何用python向钉钉机器人发送可以放大的图片?