golang中的切片传递
当前有一个函数和一个结构体定义
type s struct {
A int
}
func testFunc(l []s) {
fmt.Printf("in testFunc: %p\n",l)
}
测试 1
我们首先传递一个切片,并打印他的内存地址
func TestA(t *testing.T) {
xs := s{A: 10}
xs1 := s{A: 20}
l := []s{xs,xs1}
fmt.Printf("%p\n",l)
testFunc(l)
fmt.Printf("%p\n",l)
}
=== RUN TestA
0xc000344800
in testFunc: 0xc000344800
0xc000344800
&l引用传递
测试 2
查阅文档, “%p”还有“fmt.Printf("%p\n",&l)”这样的打印语法, 我们来试试。
func testFunc(l []s) {
fmt.Printf("in testFunc: %p\n",&l)
}
func TestA(t *testing.T) {
xs := s{A: 10}
xs1 := s{A: 20}
l := []s{xs,xs1}
fmt.Printf("%p\n",&l)
testFunc(l)
fmt.Printf("%p\n",&l)
}
=== RUN TestA
0xc000390d60
in testFunc: 0xc000390d80
0xc000390d60
TestAtestFunc
测试 3
unsafe
func testFunc(l []s) {
fmt.Println("in testFunc: ",unsafe.Pointer(&l))
fmt.Printf("in testFunc: %p\n",&l)
}
func TestA(t *testing.T) {
xs := s{A: 10}
xs1 := s{A: 20}
l := []s{xs,xs1}
fmt.Println(unsafe.Pointer(&l))
fmt.Printf("%p\n",&l)
testFunc(l)
fmt.Printf("%p\n",&l)
}
=== RUN TestA
0xc00041a240
0xc00041a240
in testFunc: 0xc00041a260
in testFunc: 0xc00041a260
0xc00041a240
unsafe%p
func testFunc(l []s) {
fmt.Println("in testFunc: ",unsafe.Pointer(&l),unsafe.Pointer(&(l[0])))
fmt.Printf("in testFunc: %p\n",&l)
}
func TestA(t *testing.T) {
xs := s{A: 10}
xs1 := s{A: 20}
l := []s{xs,xs1}
fmt.Println(unsafe.Pointer(&l),unsafe.Pointer(&(l[0])))
fmt.Printf("%p\n",&l)
testFunc(l)
fmt.Printf("%p\n",&l)
}
=== RUN TestA
0xc00000e2a0 0xc00003e280
0xc00000e2a0
in testFunc: 0xc00000e2c0 0xc00003e280
in testFunc: 0xc00000e2c0
0xc00000e2a0
l[0]0xc00003e280引用传递
测试 4
细心的小伙伴可能会提出疑问, 测试 1 打印的明明都是一样的,你这样不能自圆其说。
别着急, 那我们继续测试.
func testFunc(l []s) {
fmt.Println("in testFunc: ",unsafe.Pointer(&l),unsafe.Pointer(&(l[0])),unsafe.Pointer(&(l[1])))
fmt.Printf("in testFunc: %p\n",l)
}
func TestA(t *testing.T) {
xs := s{A: 10}
xs1 := s{A: 20}
l := []s{xs,xs1}
fmt.Println(unsafe.Pointer(&l),unsafe.Pointer(&(l[0])),unsafe.Pointer(&(l[1])))
fmt.Printf("%p\n",l)
testFunc(l)
fmt.Printf("%p\n",l)
}
=== RUN TestA
0xc000418300 0xc000420140 0xc000420148
0xc000420140
in testFunc: 0xc000418340 0xc000420140 0xc000420148
in testFunc: 0xc000420140
0xc000420140
%p0("%p",l)0("%p",&l)
测试 5
引用传递
func testFunc(l []s) {
fmt.Println("in testFunc(begin): ",l)
l[0].A = 10
fmt.Println("in testFunc(after): ",l)
}
func TestA(t *testing.T) {
xs := s{A: 10}
xs1 := s{A: 20}
l := []s{xs,xs1}
fmt.Println("begin: ",l)
testFunc(l)
fmt.Println("after: ",l)
}
testFunc0
=== RUN TestA
begin: [{10} {20}]
in testFunc(begin): [{10} {20}]
in testFunc(after): [{1} {20}]
after: [{1} {20}]
测试3
测试 6
那我们向切片中添加元素会发生什么?
func testFunc(l []s) {
fmt.Println("in testFunc(begin): ",l)
l = append(l, s{A: 30})
fmt.Println("in testFunc(after): ",l)
}
func TestA(t *testing.T) {
xs := s{A: 10}
xs1 := s{A: 20}
l := []s{xs,xs1}
fmt.Println("begin: ",l)
testFunc(l)
fmt.Println("after: ",l)
}
testFunc
=== RUN TestA
begin: [{10} {20}]
in testFunc(begin): [{10} {20}]
in testFunc(after): [{10} {20} {30}]
after: [{10} {20}]
测试3
测试 7
测试6引用传递
func testFunc(l *[]s) {
fmt.Println("in testFunc(begin): ",l)
_l := *l
_l = append(_l, s{A: 30})
l = &_l
fmt.Println("in testFunc(after): ",l)
}
func TestA(t *testing.T) {
xs := s{A: 10}
xs1 := s{A: 20}
l := []s{xs,xs1}
fmt.Println("begin: ",l)
testFunc(&l)
fmt.Println("after: ",l)
}
append_l
=== RUN TestA
begin: [{10} {20}]
in testFunc(begin): &[{10} {20}]
in testFunc(after): &[{10} {20} {30}]
after: [{10} {20}]
咦? 还是没变。别着急, 我们换一种写法。
func testFunc(l *[]s) {
fmt.Println("in testFunc(begin): ",l)
*l = append(*l, s{A: 30})
fmt.Println("in testFunc(after): ",l)
}
func TestA(t *testing.T) {
xs := s{A: 10}
xs1 := s{A: 20}
l := []s{xs,xs1}
fmt.Println("begin: ",l)
testFunc(&l)
fmt.Println("after: ",l)
}
结果
=== RUN TestA
begin: [{10} {20}]
in testFunc(begin): &[{10} {20}]
in testFunc(after): &[{10} {20} {30}]
after: [{10} {20} {30}]
是不是变了? 至于为什么… 就交给你们写到评论里啦。
总结
("%p",l)("%p",&l)