go语言的函数都是拷贝
数组
func myFunction(i int, arr [2]int) {
i = 29
arr[1] = 88
fmt.Printf("in my_funciton - i=(%d, %p) arr=(%v, %p)\n", i, &i, arr, &arr)
}
func main() {
i := 30
arr := [2]int{66, 77}
fmt.Printf("before calling - i=(%d, %p) arr=(%v, %p)\n", i, &i, arr, &arr)
myFunction(i, arr)
fmt.Printf("after calling - i=(%d, %p) arr=(%v, %p)\n", i, &i, arr, &arr)
}
$ go run main.go
before calling - i=(30, 0xc000072008) arr=([66 77], 0xc000072010)
in my_funciton - i=(29, 0xc000072028) arr=([66 88], 0xc000072040)
after calling - i=(30, 0xc000072008) arr=([66 77], 0xc000072010)
结构体和指针
type MyStruct struct {
i int
}
func myFunction(a MyStruct, b *MyStruct) {
a.i = 31
b.i = 41
fmt.Printf("in my_function - a=(%d, %p) b=(%v, %p)\n", a, &a, b, &b)
}
func main() {
a := MyStruct{i: 30}
b := &MyStruct{i: 40}
fmt.Printf("before calling - a=(%d, %p) b=(%v, %p)\n", a, &a, b, &b)
myFunction(a, b)
fmt.Printf("after calling - a=(%d, %p) b=(%v, %p)\n", a, &a, b, &b)
}
$ go run main.go
before calling - a=({30}, 0xc000018178) b=(&{40}, 0xc00000c028)
in my_function - a=({31}, 0xc000018198) b=(&{41}, 0xc00000c038)
after calling - a=({30}, 0xc000018178) b=(&{41}, 0xc00000c02
map
map结构
type hmap struct {
count int
flags uint8
B uint8
noverflow uint16
hash0 uint32
//桶
buckets unsafe.Pointer
oldbuckets unsafe.Pointer
nevacuate uintptr
extra *mapextra
}
type mapextra struct {
overflow *[]*bmap
oldoverflow *[]*bmap
nextOverflow *bmap
}
结论:
函数中改变map的值会影响函数外的map变化,由于map的桶指向是一个地址函数传递的时候会拷贝当前的地址的值,当map扩容的时候桶的值会传给oldbuckets 取值,所以修改map的值会影响函数外的map的变化
func TestValue(t map[int]int) {
fmt.Printf("%v %p\n", t, &t)
t[1] = 2
fmt.Printf("%v %p\n", t, &t)
}
func main() {
t := make(map[int]int, 0)
t[1] = 1
fmt.Printf("%v %p\n", t, &t)
TestValue(t)
fmt.Printf("%v %p\n", t, &t)
}
输出
map[1:1] 0xc000006028
map[1:1] 0xc000006038
map[1:2] 0xc000006038
map[1:2] 0xc000006028
切片
结构
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
结论:
1.数组在不超过其初始化容量的时候,修改当前data所指地址的值所以例子1中修改切片的值会修改切片的内容。
2.例子2中当超过切片容量时,Data指针地址产生变化会形成一个新的数组,由于函数传递是值拷贝所以只会修改当前切片的值。
例子1
func main() {
s := make([]int, 2)
fmt.Printf("%v %p\n", s, &s)
mdSlice(s)
fmt.Printf("%v %p\n", s, &s)
}
func mdSlice(s []int) {
fmt.Printf("%v %p\n", s, &s)
s[0] = 1
s[1] = 2
fmt.Printf("%v %p\n", s, &s)
}
输出:
[0 0] 0xc000004078
[0 0] 0xc0000040a8
[1 2] 0xc0000040a8
[1 2] 0xc000004078
例子2
func main() {
s := make([]int, 0)
fmt.Printf("%v %p\n", s, &s)
mdSlice(s)
fmt.Printf("%v %p\n", s, &s)
}
func mdSlice(s []int) {
fmt.Printf("%v %p\n", s, &s)
s = append(s, 1)
s = append(s, 2)
fmt.Printf("%v %p\n", s, &s)
}
输出
[] 0xc000004078
[] 0xc0000040a8
[1 2] 0xc0000040a8
[] 0xc000004078