go語言的函數(shù)都是拷貝
數(shù)組
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)
結(jié)構(gòu)體和指針
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結(jié)構(gòu)
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
}
結(jié)論:
函數(shù)中改變map的值會影響函數(shù)外的map變化缀皱,由于map的桶指向是一個地址函數(shù)傳遞的時候會拷貝當(dāng)前的地址的值磅甩,當(dāng)map擴容的時候桶的值會傳給oldbuckets 取值,所以修改map的值會影響函數(shù)外的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
切片
結(jié)構(gòu)
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
結(jié)論:
1.數(shù)組在不超過其初始化容量的時候怪得,修改當(dāng)前data所指地址的值所以例子1中修改切片的值會修改切片的內(nèi)容编曼。
2.例子2中當(dāng)超過切片容量時晕鹊,Data指針地址產(chǎn)生變化會形成一個新的數(shù)組浅浮,由于函數(shù)傳遞是值拷貝所以只會修改當(dāng)前切片的值。
例子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