go language basic value transfer

 3 minutes to read

go language basic value transfer

There is only value passing in go language, no reference passing

Pass-by-value refers to copying the actual parameter and passing it to the function when calling the function, so that if the parameter is modified in the function, it will not affect the actual parameter. The evaluation of the parameter address outside the function and inside the function should be Different.

Passing by reference means that the address of the actual parameter is directly passed to the function when the function is called, then the modification of the parameter in the function will affect the actual parameter.

The difference between passing by value and passing by reference is not what is passed, but whether the actual parameter is copied to the formal parameter. When judging whether the content of the actual parameter is affected, it depends on what is being passed. If you are passing an address, it depends on whether the change of the address will have any effect, not the change of the object pointed to by the address.

package main

import "fmt"

func main() {
	slice := []int{0,1,2,3}
	m := make(map[string]string)
	m["A"] = "a"
	var i *int
	a := 123
	i = &a
	fmt.Printf("[main pointer] %p\n", &i)
	fmt.Printf("[main map] %p\n", &m)
	fmt.Printf("[main slice] %p\n", &slice)
	get(slice, m, i)
	fmt.Println(slice)
	fmt.Println(m)
	fmt.Println(*i)
}

func get(s []int, m map[string]string, i *int)  {
	fmt.Printf("[get pointer] %p\n", &i)
	fmt.Printf("[get map] %p\n", &m)
	fmt.Printf("[get slice] %p\n", &s)

	s[1] = 9
	m["A"] = "Hello"
	a := 456
	i = &a
}

The results are as follows:

[main pointer] 0xc00000e030
[main map] 0xc00000e028
[main slice] 0xc00000c030
[get pointer] 0xc00000e048
[get map] 0xc00000e040
[get slice] 0xc00000c048
[0 9 2 3]
map[A:Hello]
123

It can be found that the addresses of slices, maps, and pointers have all changed during the transfer process, which means that a copy is passed.

But we also found that modifying slice and map in the function will also change the value outside the function. Why is this?

The slice itself is a structure, and the definition in the source code is as follows:

type slice struct {
    array unsafe.Pointer
    len int
    cap int
}

The bottom layer of the slice points to the array through a pointer, so the slice inside the function and the array accessed by the slice outside the function have the same address. Modifying the slice inside the function will also affect the slice outside the function.

package main

import (
	"fmt"
	"log"
)

var str []string

func main()  {
	fmt.Printf("[main slice] %p\n", str)
	fmt.Printf("[main slice] %p\n", &str)
	str=[]string{"c"}
	fmt.Printf("[main slice c] %p\n", str)
	fmt.Printf("[main slice c] %p\n", &str)
	setVal(&str)

	log.Println(str)
}

func setVal(val *[]string)  {
	fmt.Printf("[val slice] %p\n", &val)
	*val = []string{"a", "b"}
	fmt.Printf("[val slice] %p\n", val)
}

The results are as follows:

[main slice] 0x0
[main slice] 0x113e0b0
[main slice c] 0xc000010230
[main slice c] 0x113e0b0
[val slice] 0xc00000e030
[val slice] 0x113e0b0
[a b]