Value passed

In Golang, all parameters are passed by value, that is, a copy of the passed parameter variable.

For example, if we pass a parameter of type int, we pass a copy of the parameter. Passing a pointer argument is actually passing a copy of the pointer, not the value to which the pointer points.

The sample

package main
import (
	"fmt"
)
func main(a) {
	i:=10
	ip:=&i
	fmt.Printf("The memory address of the original pointer is: %p\n",&ip)
	modify(ip)
	fmt.Println("Int value changed, new value :",i)
}
func modify(ip *int){
	 fmt.Printf("The memory address of the pointer received in the function is: %p\n",&ip)
 	*ip=1
 }
Copy the code

Output:

The memory address of the pointer received in the function is 0xC0000a0028. The int value has been changed to: 1Copy the code

Reference types

Golang’s reference types include Slice, Map, and Channel. With the exception of pointer types, changes within a function can still affect values outside the function when the parameters are Slice, Map, or Channel.

The sample

package main
import (
	"fmt"
)
func main(a) {
	s := []int{1.2.3}
	modify(s)
	fmt.Println(s)
}

 func modify(s []int){
         s[0] = 0
 }
Copy the code

Output:

[0 2 3]

Program exited.
Copy the code

The principle of

Slice

In Golang, the data structure of Slice is defined as follows:

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

When slice is passed, the structure is passed by value, and when it is passed, there are two slice structures in memory that reference the same slice array.

The sample

package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

func main(a) {
 s := []string{"a"."b"}

 fmt.Printf("%p\n", (*reflect.SliceHeader)(unsafe.Pointer(&s)))
 sliceData(s)
}
func sliceData(s []string) {
    fmt.Printf("%p\n", (*reflect.SliceHeader)(unsafe.Pointer(&s)))
}
Copy the code

Output:

0xc00000c030
0xc00000c048
Copy the code

SliceHeader

SliceHeader is a representation of Slice runtime, which can be cast to reflect.SliceHeader via unsafe.Pointer.

type SliceHeader struct {
	Data uintptr
	Len  int
	Cap  int
}
Copy the code

Map

For map, the make function returns a pointer of type hmap *hmap. So when you pass, you’re passing a copy of this pointer.

// makemap implements a Go map creation make(map[k]v, hint) // If the compiler has determined that the map or the first bucket // can be created on the stack, h and/or bucket may be non-nil. // If h ! = nil, the map can be created directly in h. // If bucket ! = nil, bucket can be used as the first bucket. func makemap(t *maptype, hint int64, h *hmap, Bucket unsafe.Pointer) *hmap {// omit irrelevant code}Copy the code

Chan

The same is true for MAP.

Func makechan(t *chantype, size int64) *hchan {Copy the code

use

capacity

If a Slice expansion is triggered because of the capacity, references inside and outside the function will be different.

package main
import (
	"fmt"
)
func main(a) {
	s := []int{1.2.3}
	modify(s)
	fmt.Println(s)
}
func modify(s []int){
	s = append(s, 4)
	s[0] = 0
	fmt.Println(s)
 }
Copy the code

Output:

[0 2 3 4]
[1 2 3]
Copy the code

How to modify the original slice under capacity expansion

In addition to returning a new slice, you can also pass a pointer to the slice

func myAppend(list *[]string, value string) {
    *list = append(*list, value)
}
Copy the code

Pass arrays using slice

When an array is used as a parameter, a copy of it is made. If it is very large, “it will cause a lot of memory waste”, using [:] to pass the array as a slice.

package main
import (
	"fmt"
)
func main(a) {
	a := [3]int{1.2.3}
	print(a[:])
}
func print(a []int){
         fmt.Println(a)
 }
Copy the code

www.flysnow.org/2018/02/24/…

zhuanlan.zhihu.com/p/401758344