Golang 数组(切片)的值传递与引用传递

Go语言中函数的参数都是按值进行传递的,即使参数是指针,也是指针的一个副本。习惯上把指针的函数参数称之为地址传参,即引用传递,而非指针的函数参数称为值传参
地址传参在大对象上效率比值传参好,在内部相当于用指针地址赋值,而不用复制整个对象

一、数组的值传递

Golang数组作为参数传入函数时,进行的是值传递,这里与Java数组的引用传递是不同的,示例如下

package main

import "fmt"

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

	fmt.Println(arr)
	exchange(arr)
	fmt.Println(arr)
}

func exchange(arr [8]int) {
	for k, v := range arr {
		arr[k] = v * 2
	}
}

运行结果如下:
在这里插入图片描述

二、数组的引用传递

需要注意的是,golang中本质上是没有引用传递的,这里只不过是通过值传递来传递指针,main函数的arr和exchangeByAddress的arr地址是不一致的,但是他们指针的值是相同的,也就是修改的同一块内存的数据,所以能实现引用传递的效果

默认情况下Golang的数组传递是值传递,但当我们想要对传入的数组进行修改时,可以使用指针来对数组进行操作,如下

package main

import "fmt"

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

	fmt.Println(arr)
	exchangeByAddress(&arr)
	fmt.Println(arr)
}

func exchangeByAddress(arr *[8]int) {
	for k, v := range *arr {
		arr[k] = v * 2
	}
}

运行结果如下:
在这里插入图片描述

三、切片的引用传递(本质依旧是指针的值传递)

Golang中的切片与Java中的ArrayList集合类似,进行的是引用传递
严格来说golang没有引用传递,下面示例汇总虽然在exchangeSlice内对切片的修改反馈到了main函数中,但是内部和外部的slice的地址其实是不一样的。两个slice的地址不一致,但是他们指向了同一个底层数组,在exchangeSlice函数内的变更最后反馈到了底层数组上。

package main

import "fmt"

func main() {
	slice := []int{1,2,3,4,5}
	fmt.Println(slice)
	exchangeSlice(slice)
	fmt.Println(slice)
}

func exchangeSlice(slice []int) {
	for k, v := range slice {
		slice[k] = v * 2
	}
}

运行结果:
在这里插入图片描述
这里需要格外注意,在内部exchangeSlice函数内如果发生了底层数组的扩容,那么exchangeSlice内的slice则会申请新的数组,在扩容后的slice做的变更也将不会再反馈到外部main函数的slice中

package main

import "fmt"


func main() {
	slice := []int{1,2,3}
	fmt.Println(slice)
	exchangeSlice(slice)
	fmt.Println(slice)
}

func exchangeSlice(slice []int) {
	slice = append(slice, 4, 5, 6); // 原始数组大小为4,超过4会扩容
	for k, v := range slice {
		slice[k] = v * 2
	}
	fmt.Println(slice)
}

运行结果:
在这里插入图片描述

  • 16
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
在Go语言中,可以使用以下代码来求一个数组的最大值: ```go func max(nums []int) int { if len(nums) == 0 { return 0 } max := nums[0] for i := 1; i < len(nums); i++ { if nums[i] > max { max = nums[i] } } return max } ``` 这段代码使用了一个循环来遍历整个数组,并且使用一个变量来记录当前的最大值。如果当前元素比最大值还要大,就更新最大值。最后返回最大值即可。 为了提高性能,我们可以使用Go语言的并发机制来加速这个过程。例如,我们可以将数组分成多个小块,每个小块都在单独的goroutine中执行最大值计算,然后使用一个goroutine来汇总所有的结果并找出最大值。这样可以有效地利用多核CPU的性能,并且在处理大型数组时可以更快地得到结果。 以下是一个使用并发计算最大值的示例代码: ```go func max(nums []int) int { if len(nums) == 0 { return 0 } numChunks := runtime.NumCPU() chunkSize := (len(nums) + numChunks - 1) / numChunks ch := make(chan int, numChunks) for i := 0; i < numChunks; i++ { start := i * chunkSize end := start + chunkSize if end > len(nums) { end = len(nums) } go func(nums []int) { max := nums[0] for i := 1; i < len(nums); i++ { if nums[i] > max { max = nums[i] } } ch <- max }(nums[start:end]) } max := nums[0] for i := 0; i < numChunks; i++ { if result := <-ch; result > max { max = result } } return max } ``` 这段代码将数组分成了多个小块,并且在每个小块上启动了一个goroutine来计算最大值。每个goroutine都会将结果发送到一个channel中,然后主goroutine会从channel中读取所有的结果并找出最大值。由于我们使用了多个goroutine进行计算,因此可以得到更快的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值