Is there a reference pass for a function parameter in Golang?

Source: Internet
Author: User

Following the previous article, continue to explore several questions:

    1. What is the difference between a value pass in a function pass, a pointer pass, and a reference pass?
    2. Why Slice,map,Channel is a reference type?
    3. Does slice in Go pass in the function when it is passed? If not, why is it possible to modify its value inside a function?
in a function call, the function value and arguments is evaluated in the usual order. After they is evaluated, the parameters of the call is passed by value to the function and the called Functio N begins execution.
Document address: Https://golang.org/ref/spec#C
...

Official documentation has made it clear that thego inside function passes only one way , in order to strengthen their understanding, and then to each kind of communication method to comb.

Value passing

value passing means that a copy of the actual parameter is passed to the function when the function is called, so that if the parameter is modified in the function, the actual argument will not be affected.

The concept always gives a sense of a textbook, which writes point code under verification.

func main() {    a := 10    fmt.Printf("%#v\n", &a) // (*int)(0xc420018080)    vFoo(a)}func vFoo(b int) {    fmt.Printf("%#v\n", &b) // (*int)(0xc420018090)}

The comment content is the output of my machine, you will get different output if you run

According to the code, the so-called value is passed: When argument a is passed to the parameter b of the function Vfoo , within Vfoo ,b is allocated space on the stack as a local variable, and completely copy the value of a .

After the code executes, the result we see is: A, B has a completely different memory address, indicating that although they have the same value (b copy of A, the value is certainly the same), but in different places in memory, and therefore within the function Vfoo If you change the value of b , a is not affected.

On the left side of the graph, the memory is allocated when it is not yet called, and the right side is the variable allocated by the memory when the function is called. It is important to note that even if the Vfoo parameter name is a, the real participation parameters have their own memory space, because the parameter name is only for programmers to see, the previous article has been made clear.

Pointer passing

A parameter is a pointer to the address of an argument that, when directed to a parameter, is the equivalent of an
action on the argument itself.

Isn't that foggy? or by combining code to analyze so-called pointer passing.

func main() {    a := 10    pa := &a    fmt.Printf("value: %#v\n", pa) // value: (*int)(0xc420080008)    fmt.Printf("addr: %#v\n", &pa) // addr: (**int)(0xc420088018)    pFoo(pa)}func pFoo(p * int) {    fmt.Printf("value: %#v\n", p) // value: (*int)(0xc420080008)    fmt.Printf("addr: %#v\n", &p) // addr: (**int)(0xc420088028)}

A variable A is defined and the address is stored inside the pointer variable PA. According to our conclusion,only the value of Go passes , then the pointer variable PA passes to the function's parameter p, the shape arguments will be a copy of it on the stack, they will each have a different address, but the value of the two is the same (all the address of variable a). The above comment section is the result of my program running, PA and P address each other, indicating that a value copy occurred in the parameter pass.

In the function Pfoo , the address of the formal parameter p is not the same as the address of the actual parameter PA, but their value in memory is the address of variable A, so you can change the value of a by using pointer-related actions.

In the figure, &a represents the address of a, and the value is: 0xc420080008

Reference delivery

so-called reference passing means that the address of the actual parameter is passed to the function when the function is called, and the modification of the parameter in the function will affect the actual parameter.

Since there is no reference passing in go, we often see that the reference pass in Go is also for:Slice,Map,Channel types (This is a false view), so in order to explain clear reference delivery, First of all, let's look at a C + + code (of course very simple).

void rFoo(int & ref) {    printf("%p\n", &ref);// 0x7ffee5aef768}int main() {    int a = 10;      printf("%p\n", &a);// 0x7ffee7307768    int & b = a;    printf("%p\n", &b);// 0x7ffee5aef768    rFoo(b);    return 0;}

Here is the simple definition of a reference in main, and then to the function Rfoo, so to see what the Orthodox reference delivery is?

Here B is the alias of a (reference, not clear can see my previous article), so a, B must have the same address. Then, following the definition passed by reference, when argument B is passed to formal parameter ref, ref will be the alias of B (that is, a, B, ref are the same variable) and they will have the same address. By printing information in the rfoo function, you can see that the three have exactly the same address, which is called a reference pass.

No reference delivery in Go

function calls in Go are only value-passed, but type references have reference types:slice,map,channel. Take a look at the official statement:

There's a lot of history on that
topic. Early on, maps and channels were syntactically pointers and it is impossible to declare or use a Non-pointer instance. Also, we struggled with how to arrays should work. Eventually we decided the strict separation of pointers and values made the language harder to use. Changing these types to act as references to the associated, shared data structuresresolved these issues. This change added some regrettable complexity to the language it had a large effect on Usability:go became a more produc tive, comfortable language when it was introduced.

It is probably meant to say that the first use of pointer syntax, for a variety of reasons changed to a reference, but this reference is different from C + +, it is the structure of sharing the associated data. An in-depth discussion of this issue will be discussed in slice related articles, and now go back to the topic discussed today.

So where does the go reference pass source? I think the misunderstanding is that the reference type of map, slice, channel, and so on is passed inside the function and can be modified within the function to modify its value.

For these three types is passed by value , we use slice to verify.

func main() {    arr := [5]int{1, 3, 5, 6, 7}    fmt.Printf("addr:%p\n", &arr)// addr:0xc42001a1e0    s1 := arr[:]    fmt.Printf("addr:%p\n", &s1)// addr:0xc42000a060    changeSlice(s1)}func changeSlice(s []int) {    fmt.Printf("addr:%p\n", &s)// addr:0xc42000a080    fmt.Printf("addr:%p\n", &s[0])// addr:0xc42001a1e0}

The code defines an array of arr, and then uses it to generate a slice. If there is a reference pass in go, the address of the formal parameter s should be the same as the argument S1 (the proof of C + +), and through the actual situation we find that they have a completely different address, that is, the transfer parameter still has a copy-value transfer.

But here is a strange phenomenon, you see arr 's address and S[0] have the same address, which is why we can modify the slice inside the function, because when it passed as a parameter to the function, although slice itself is a value copy, However, it references the structure of the corresponding array internally, so S[0] is a reference to arr[0] , which is why it can be modified.

Summary

    • The function parameter in Go only has the value passing one way;
    • Slice,map,channel are reference types, but different from C + +;
    • Slice can modify the corresponding array value after the function is passed, because the slice internally holds a pointer to the reference array, not because the reference is passed.

The next article tries to parse the following:
Slice why does it have to be initialized with make, and what does it initialize? What does it do each time it dynamically expands capacity?

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.