Go Language Method value receiver, Pointer receiver a variety of experimental notes for different situations

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. Note: This article is just my personal note, if there is a fallacy, error, please be sure to point out!
For range issues
Http://stackoverflow.com/questions/30577212/go-for-range-slice-and-goroutine-method-invocation-the-logic-behind
Package Mainimport ("FMT" "Time") Type field struct {name String}func (P *field) print () {fmt. Printf ("Print:p:%p, V:%s\n", p, P.name)}func main () {data: = []field{{"One"},{"one"},{"three"}} for _,v: = R Ange Data {//NOTE: The iteration variable in the For statement (for example: v) is reused at each iteration and has been reused go v.print ()//Note: Go (&v). Print (), which is called with a pointer to V,    and V will be reused at each iteration, so each receiver is a pointer to V, and V is assigned a value of "three" after the last iteration, so the result of printing out 3 "three". } time. Sleep (3 * time. Second)//goroutines Print:three, three, three}
Package Mainimport ("FMT" "Time") Type field struct {name String}func (P *field) print () {fmt. Println (P.name)}func main () {data: = []*field{{"One"},{"one"},{"three"}} for _,v: = Range data {Go V.PR the int ()//v itself is the pointer, pointing to one, the other, the three; The iteration will change the point, the direct call is not copied, the direct call, so each call when the V is pointed to one, two, three address value, of course, will print the correct results;    Unlike the previous example, in the above example, because of the multiplexing of V, each invocation of the pointer receiver together points to V, but the value of v after the loop is finally assigned the value: three, so the error result occurs. } time. Sleep (3 * time. Second)}//goroutines Print:one, I, three
Note: Four elements explain the above two examples:
Prerequisite: The method is defined as pointer receiver.
Func ( P *field) print () {fmt. Printf ("Print:p:%p, V:%s\n", p, P.name)}
(1) Pointer receiver does not replicate under the precondition, so when called by value, the &value takes the address directly as Pointer receiver.
(2) If the precondition is satisfied,For _,v: = in range data v itself is a pointer, which is called directly. (3) for range is multiplexed in each iteration with V (4) The Go language itself is a value semantics, that is, the reference, call, iteration will be copied, but like: pointers, reference types just copy itself, not its point to the data, so the cost of replication is very low, but the array is a value type, the whole copy yo. Detailed analysis is available in the resources link.
Explanation in StackOverflow: This is a very common technique in go. The iteration variables in the For statement are reused for each iteration. This means that the closure (that is, the function literal) you create in the For loop will refer to the same variable (and the value of that variable will be obtained when those goroutine start executing).
In the first loop, vis the valueof a FieldItem. Because vIs addressable, it's automatically referenced as the pointer receiver for the print ()Method. So V.print ()is using the address of vitself, and the contents of that address are overwritten each iteration of the loop. When you change the declaration to use a *field, vis now a pointer to a FieldValue. When to call V.print ()In this case, you is operating on the value of that vPoints to, which are stored in Data, and the overwriting of vhas no effect.
----------------------------------------------------My trial Code---------------------------------package main
Import "FMT" import "Time"
Type A int
Func (A A) valuereceiver () {

Fmt. Printf ("Valuereceiver, P:%p, V:%d\n", &a, a)}func (a A) Valuereceiveringo () {

Fmt. Printf ("Valuereceiveringo, P:%p, v:%d\n", &a, a)}func (a A) Valuereceiverindefer () {
Fmt. Printf ("Valuereceiverindefer, P:%p, v:%d\n", &a, a)}
Func (A A) Valuerececiverinforrange () {
Fmt. Printf ("Valuerececiverinforrange, P:%p, V:%d\n", &a, a)}func main () {var a a = 1fmt. Printf ("Main, p:%p, V:%d\n", &a, a) a.valuereceiver () P: = &ap. Valuereceiver ()//------------call in Goroutine--------go A.valuereceiveringo () go P.valuereceiveringo () time. Sleep (*. Second)//---------call in defer----------defer a.valuereceiverindefer () defer p.valuereceiverindefer ()//---call in For range array, value receiver---as: = [5]a{1,2,3,4,5}fmt. Printf ("as[0]:%p,%d\n", &as[0], as[0]) for _, A: = range as {fmt. Printf ("As in for:%p,%d\n", &as[0], as[0]) fmt. Printf ("A In for:%p, V:%d\n", &a, a) A.valuerececiverinforrange () PF: = &apf. Valuerececiverinforrange ()}}

Results Main, p:0x10434114, v:1
Valuereceiver, p:0x1043411c, v:1
Valuereceiver, p:0x10434134, v:1
Valuereceiveringo, p:0x1043413c, v:1
Valuereceiveringo, p:0x10434144, v:1
As[0]: 0x10430240, 1
As in for:0x10430240, 1
A in for:0x10434150, v:1
Valuerececiverinforrange, p:0x1043415c, v:1
Valuerececiverinforrange, p:0x10434164, v:1
As in for:0x10430240, 1
A in for:0x10434150, V:2
Valuerececiverinforrange, p:0x10434174, V:2
Valuerececiverinforrange, p:0x1043417c, V:2
As in for:0x10430240, 1
A in for:0x10434150, V:3
Valuerececiverinforrange, p:0x1043418c, V:3
Valuerececiverinforrange, p:0x10434194, V:3
As in for:0x10430240, 1
A in for:0x10434150, V:4
Valuerececiverinforrange, P:0X104341A4, V:4
Valuerececiverinforrange, P:0X104341AC, V:4
As in for:0x10430240, 1
A in for:0x10434150, V:5
Valuerececiverinforrange, P:0X104341BC, V:5
Valuerececiverinforrange, P:0X104341C4, V:5
Valuereceiverindefer, p:0x104341cc, v:1
Valuereceiverindefer, P:0X104341D4, v:1 Conclusion: By analyzing the above address, for the value Receciver method, all kinds of invocation mode, is the copy of the original value, that is, the copy is called Receiver, Even if it is invoked as a pointer, it is called after the copy is generated by *pointer, and it is also noted that a (for _, A: = range as) is reused in the for range.------------------------------------------ ---------------------------------------------------------------------------------Pointer Receiver Test--------------------------
Package Main
Import "FMT" import "Time"
Type A int
Func (P *a) Pointerreceiver () {
Fmt. Printf ("Pointerreceiver, P:%p, V:%d\n", p, *p)}func (P *a) Pointerreceiveringo () {
Fmt. Printf ("Pointerreceiveringo, P:%p, V:%d\n", p, *p)}func (P *a) Pointerreceiverindefer () {
Fmt. Printf ("Pointerreceiverindefer, P:%p, V:%d\n", p, *p)}func (P *a) Pointerreceiverinforrange () {
Fmt. Printf ("Pointerreceiverinforrange, P:%p, V:%d\n", p, *p)}func main () {
var a = 1fmt. Printf ("Main, p:%p, V:%d\n", &a, a) a.pointerreceiver () P: = &ap. Pointerreceiver ()//------------------go A.pointerreceiveringo () go P.pointerreceiveringo () time. Sleep (*. Second)//------------------defer A.pointerreceiverindefer () defer p.pointerreceiverindefer ()//------------------ as: = [5]a{1,2,3,4,5}fmt. Printf ("As[0", p:%p, V:%d\n ", &as[0], as[0]) for _, A: = range as {fmt. Printf ("As in For:p:%p, V:%d\n", &as[0], as[0]) fmt. Printf ("A in for:p:%p, V:%d\n", &a, a) A.pointerreceiverinforrange () P: = &ap. Pointerreceiverinforrange ()}}
Results: Main, p:0x10434114, v:1
Pointerreceiver, p:0x10434114, v:1
Pointerreceiver, p:0x10434114, v:1
Pointerreceiveringo, p:0x10434114, v:1
Pointerreceiveringo, p:0x10434114, v:1
As[0], p:0x10430240, v:1
As in For:p: 0x10430240, V:1
A in For:p: 0x10434140, V:1
Pointerreceiverinforrange, p:0x10434140, v:1
Pointerreceiverinforrange, p:0x10434140, v:1
As in For:p: 0x10430240, V:1
A in For:p: 0x10434140, V:2
Pointerreceiverinforrange, p:0x10434140, V:2
Pointerreceiverinforrange, p:0x10434140, V:2
As in For:p: 0x10430240, V:1
A in For:p: 0x10434140, V:3
Pointerreceiverinforrange, p:0x10434140, V:3
Pointerreceiverinforrange, p:0x10434140, V:3
As in For:p: 0x10430240, V:1
A in For:p: 0x10434140, V:4
Pointerreceiverinforrange, p:0x10434140, V:4
Pointerreceiverinforrange, p:0x10434140, V:4
As in For:p: 0x10430240, V:1
A in For:p: 0x10434140, V:5
Pointerreceiverinforrange, p:0x10434140, V:5
Pointerreceiverinforrange, p:0x10434140, V:5
Pointerreceiverindefer, p:0x10434114, v:1
Pointerreceiverindefer, p:0x10434114, v:1
Conclusion: Through the analysis of the above address, for pointer receiver method, at the time of invocation, no copy is generated, but the address of the original object itself; A In (for _, A: = range as) is reused. ---------------------------------------------------------------------------------------------------References:
https://gobyexample.com/ http://colobu.com/2015/09/07/gotchas-and-common-mistakes-in-go-golang/ http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/ http://waterdudu.github.io/post/go-tips/ https://www.yushuangqi.com/blog/2015/7_things-you-may-not-pay-attation-to-in-go.html http://www.qiukeke.com/2015/05/28/gotchas-and-common-mistakes-in-go-golang.html http://tonybai.com/2015/09/17/7-things-you-may-not-pay-attation-to-in-go/

Note: This article is only my personal notes, if there are errors and omissions, please correct me, study together, my e-mail: htyu_0203_39@sina.com


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.