golang:数组的传递(引用传递、指针传递、值传递)

概念介绍

数组与切片

  • 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列。数组长度最大为2Gb,它是值类型。
  • 切片是对数组一个连续片段的引用,所以切片是一个引用类型。

按值传递和按引用传递

Go语言中函数的参数有两种传递方式,按值传递和按引用传递。

  • Go默认使用按值传递来传递参数,也就是传递参数的副本。在函数中对副本的值进行更改操作时,不会影响到原来的变量。
  • 按引用传递其实也可以称作”按值传递”,只不过该副本是一个地址的拷贝,通过它可以修改这个值所指向的地址上的值。

golang中,在函数调用时,引用类型(slice、map、interface、channel)都默认使用引用传递。

数组传递时的缺点

一般情况下,传递指针的消耗比传递副本的少,尤其是当数组特别大时。具体原因是:

  • 值传递需要完整的复制初始数组并将这份拷贝放到栈中,这将耗费大量运行时间,因而值传递方式的效率比较低。
  • 初始数组的拷贝需要占用额外的内存空间(栈中的内存)
  • 编译程序需要专门产生一部分用来复制初始数组的代码,这将使程序变大。

如何避免

如上面介绍的,有两种方法,第一种利用指针,即引用传递;第二种使用切片,因为切片是引用类型,默认会使用引用传递。

func main() {
	var arr = [5]int{1, 2, 3, 4, 5}
	mod(arr[:]) //[0 1 2 3 4]  ---- 使用切片进行传递: 因为切片是引用类型,默认会使用引用传递。
	fmt.Println(arr)

	arr = [5]int{1, 2, 3, 4, 5}
	mod2(arr) //[1 2 3 4 5]
	fmt.Println(arr)  //------传递副本

	arr = [5]int{1, 2, 3, 4, 5}
	mod3(&arr)
	fmt.Println(arr) //[0 1 2 3 4]  利用指针

	var p *[]int
	var brr = []int{1, 2, 3, 4, 5}
	p = &brr
	mod4(p) 
	fmt.Println(brr) //[0 1 2 3 4]  

}

func mod(arr []int) {
	for i := 0; i < len(arr); i++ {
		arr[i] = i
	}
}

func mod2(arr [5]int) {
	for i := 0; i < len(arr); i++ {
		arr[i] = i
	}
}

func mod3(arr *[5]int) {
	for i := 0; i < len(arr); i++ {
		arr[i] = i
	}
}

func mod4(arr *[]int) {
	for i := 0; i < len(*arr); i++ {
		(*arr)[i] = i
	}
}

易错点【append】

func main() {
	var arr = []int{1, 2, 3, 4, 5}
	mod(arr[:]) //[1 2 3 4 5]  在对slice进行append操作的时候,返回的是新的引用,并非原始引用
	fmt.Println(arr)

	arr = []int{1, 2, 3, 4, 5}
	mod4(&arr) //[1 2 3 4 5 6]
	fmt.Println(arr)

}

func mod(arr []int) {
	arr = append(arr, 6)
}


func mod4(arr *[]int) {
	(*arr) = append((*arr), 6)
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值