在新的项目中,用到的Goland。以前用Python做项目,Python基本变量的赋值是引用重定向。Goland有些不一样,这里做个测试
直接利用打印变量值、地址的方式确认变量拷贝情况
package main
import "fmt"
func getInt() int {
i := 5
println("in getInt, i", i, &i)
return i
}
func intTest(i int) {
println("in intTest, i", i, &i)
i = 99
}
func listTest(list []int) {
println("in listTest, list", &list, list)
list[0] = 99
}
func mapTest(mapInt map[int]int) {
println("in mapTest, mapInt", mapInt, &mapInt)
mapInt[99] = 100
}
func main() {
t := 1
fmt.Println("in main, t", t, &t)
t = 2
fmt.Println("in main, t", t, &t)
t = getInt()
fmt.Println("in main, t", t, &t)
intTest(t)
fmt.Println("in main, t", t, &t)
fmt.Println("*************************")
l := []int{1,2,3}
println("in main, l", &l, l)
l = []int{1,2,3,4,5}
println("in main, l", &l, l)
l2 := l
println("in main, l2", &l2, l2)
listTest(l)
fmt.Println("in main, l", l)
fmt.Println("*************************")
mapInt := make(map[int]int)
mapInt[1] = 2
println("in main, mapInt", mapInt, &mapInt)
mapTest(mapInt)
println("in main, mapInt", mapInt, &mapInt)
fmt.Println("in main, mapInt", mapInt)
}
输出结果
in main, t 1 0xc0000140a0
in main, t 2 0xc0000140a0
in getInt, i 5 0xc00006ade0
in main, t 5 0xc0000140a0
in intTest, i 5 0xc00006ade8
in main, t 5 0xc0000140a0
*************************
in main, l 0xc00006ae58 [3/3]0xc000012140
in main, l 0xc00006ae58 [5/5]0xc00001a060
in main, l2 0xc00006ae40 [5/5]0xc00001a060
in listTest, list 0xc00006ae28 [5/5]0xc00001a060
in main, l [99 2 3 4 5]
*************************
in main, mapInt 0xc00006adf0 0xc000062180
in mapTest, mapInt 0xc00006adf8 0xc000062180
in main, mapInt 0xc00006adf0 0xc000062180
in main, mapInt map[1:2 99:100]
先看第一组结果,简单int变量t,重新赋值为2后,在内存中的地址不变。与Python不同,Python简单对象赋值是引用重定向,引用一个新的对象,会改变id(obj)的结果。Goland是在原对象的基础上修改,改变原对象中的内容。函数的传参、返回值都会拷贝一个新对象,修改拷贝的对象不影响原对象。
再看第二组结果,切片类型l,打印第一个数值是变量地址,后面接的是[len/cap]数组内存地址,切片独享保留着对数组内存地址的引用。第二次对切片赋值,同样的对象地址不变,其len、cap、数组地址发生变化。在函数listTest中,形参同样会生成一个新的对象,切片拷贝对象的len、cap、数组内存地址与元对象一致,如果改变拷贝切片中的元素,由于其引用同一个连续数组内存,原对象上也会得到体现,最后main中l[0]=99
再看第三组结果,map类型,打印的第一个值是map变量的地址,第二个参数是map对象引用的数据块地址。同样的,map对象作为形参,会拷贝出一个新对象,与list类似,新老对象引用的数据块地址一致,修改拷贝对象数据块中的数据,会影响老对象的数据。