The go language's parameter and reference

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Issues with reference and pass-through

Many unofficial documents and textbooks (including some already published books), commentary on the Go language and references
Have a lot of problems. There are many misconceptions about the function parameters of go that lead to many novice go languages.

Communication and reference are the fundamental problems of programming languages, and if this problem is understood incorrectly it can cause many problems.

Chuan Slice is not a reference!

First of all, the function call parameters of the go language are all values, including slice / map / chan in all types, without reference to the argument.

For details, see the code for the Go language:

After they is evaluated, the parameters of the call is passed by value to the function and the called function Begins execution.

From:http://golang.org/ref/spec#calls

What do you mean by reference?

For example, the following code is available:

var a ObjectdoSomething(a) // 修改a的值print(a)

If the function doSomething modifies a the value and then print prints out the modified value,
Then you can assume that the doSomething parameter is used in a reference way a .

Why preach slice is not a reference?

We construct the following code:

func main() {    a := []int{1,2,3} fmt.Println(a) modifySlice(a) fmt.Println(a)}func modifySlice(data []int) { data = nil}

Where modifySlice the slices are modified a , the output is as follows:

[1 2 3][1 2 3]

Note that a modifySlice there is no change before and after the call, so it a must be a value!

Why do many people mistakenly think that slice is a reference?

It may be that the FAQ says slice is a reference type, but not a reference!

The following code may be the source of the error:

func main() {    a := []int{1,2,3}    fmt.Println(a) modifySliceData(a) fmt.Println(a)}func modifySliceData(data []int) { data[0] = 0}

The output is:

[1 2 3][0 2 3]

The function modifySliceData does modify the contents of the slice through parameters.

Note, however, that there are many mechanisms for modifying the contents of a parameter through a function, in which the address of the parameter can be modified to modify the value of the parameter (in fact, it is the data that the pointer points to in the parameter), not just a way of referencing!

Is it equivalent to passing pointers and passing references?

For example, the following code is available:

func main() {    a := new(int) fmt.Println(a) modify(a) fmt.Println(a)}func modify(a *int) { a = nil}

The output is:

0xc0100000000xc010000000

You can see that a the pointer itself does not change. Passing a pointer or a pass-through address can only modify the value of memory pointed to by the pointer.
You cannot change the value of the pointer itself.

Therefore, the function parameter pass-through pointer is also the pass value, is not the reference!

All types of function parameters are value-passed!

sliceboth the map chan underlying type and the custom type, including//, are value-passed.

However slice , because map of the differences between the structure and/or the chan underlying structures, the effect of their values is not exactly equal.

The emphasis is summarized as follows:

    • gospec:the parameters of the call is passed by value!

    • map/slice/chan are all pass values, not reference

    • map/chan corresponding pointer, and reference similar to

    • slice is a mix of structs and pointers

    • slice including values/count/capacity information, is passed by value The values in

    • slice are pointers, passed by value

    • Slice by value can only modify the data that values point to, None of the others can modify the

Does the go language have a quote?

The go language is also a reference place, but is not a function of the parameters, but the closure of the external environment is accessed by reference.

Look at the following code:

func main() {    a := new(int) fmt.Println(a) func() { a = nil }() fmt.Println(a)}

The output is:

0xc010000000<nil>

Because closures are variables that use the external environment by reference a , the values can be modified directly a .

For example, the output of the following 2-segment code is quite different, because the second code outputs the variable in the form of a closure reference i :

for i := 0; i < 5; i++ {    defer fmt.Printf("%d ", i) // Output: 4 3 2 1 0}fmt.Printf("\n") for i := 0; i < 5; i++ { defer func(){ fmt.Printf("%d ", i) } () // Output: 5 5 5 5 5}

Like the second code is the side effect of the closure reference, the way to avoid this side effect is to construct a different temporary variable by the parameter value or each closure:

// 方法1: 每次循环构造一个临时变量 ifor i := 0; i < 5; i++ { i := i defer func(){ fmt.Printf("%d ", i) } () // Output: 4 3 2 1 0}// 方法2: 通过函数参数传参for i := 0; i < 5; i++ { defer func(i int){ fmt.Printf("%d ", i) } (i) // Output: 4 3 2 1 0}

What is a reference type, and how does a pointer differ/relate?

Described in the official Go Language FAQ, maps / slices / channels is a reference type and the array is a value type:

Why is maps, slices, and channels references while arrays is values?

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 structures resolved 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.

From:http://golang.org/doc/faq#references

I personally understand that reference types and pointers are the same on the underlying implementations.
However, the reference type hides the pointer operation that is displayed on the syntax.
Reference/pass-through values are not a concept for referential types and function parameters.

We know maps / slices / channels at the bottom though the pointers are implied,
However, there is no syntax to use pointers in use.
The reference memory is, after all, based on pointer implementations, so a function must be relied upon/to be make new constructed.
Of course, they all support literal syntax constructs, but they still need a construction process in essence.

To use the reference type of the go language, it is important to understand some of the underlying structures (especially slice the hybrid structure).

We can simulate a reference type for the go language ourselves.
We can define a value type-specific array type as a reference type (while providing a constructor):

type RefIntArray2 *[2]intfunc NewRefIntArray2() RefIntArray2 {    return RefIntArray2(new([2]int))}

This allows us to RefIntArray2 use it as a reference type.

func main() {    refArr2 := NewRefIntArray2()    fmt.Println(refArr2)    modifyRefArr2(refArr2)    fmt.Println(refArr2)}func modifyRefArr2(arr RefIntArray2) {    arr[0] = 1}

The output is:

&[0 0]&[1 0]

The reason for choosing an array as an example is that the go language array pointer can be accessed directly using [] the syntax sugar.
Therefore, the reference type is generally the underlying pointer implementation, only the upper layer with the syntax of sugar only.

Note: This section complements the comments made by @hooluupog and @LoongWong.

Summarize

    • function parameter pass value, closed packet to quote!
    • Slice contains values/count/capacity and other information, is passed by value
    • Slice that are passed by value can only modify the data pointed to by values, and none of the others can be modified
    • Slice is a mixture of structures and pointers
    • Reference types and pass-through references are two concepts
from:http://my.oschina.net/chai2010/blog/161384
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.