Golang 参数传递本质

本文详细探讨了Go语言中参数传递的本质,指出所有参数都是传值,但对于切片这类引用类型,其值传递会共享底层数组。通过示例代码展示了切片在函数内的修改如何影响原切片,并解释了这种行为的原因。通过理解Go语言的内存管理和切片的工作原理,有助于开发者更好地理解和使用Go语言。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、结论

Golang 参数传递,全部是传值

二、为什么

  • 对于map,slice这样的类型,作为参数传递,明明是传值,但是在函数中修改值后,在原函数仍然能访问到修改后的值。
  • 如果你有C++基础,那么对于slice的理解,很容易就懂了,Slice的内部,就是这么个东东.
template<typename T>
class Slice {
public:
 ~Slice();
 Slice(size_t len , size_t cap)
 Slice(const Slice&v);
 // 下面这三个成员,非常的重要
 T* Data; //array of datas
 size_t Len;
 size_t Cap;
};

  • 函数之间的传值,是浅拷贝
  • 所以你在函数之间使用slice传值,是完全ok的,他们都共享Data指针(前提是append时,有足够的空间(cap),否则会生成新的slice,这个新的slice跟之前的,就没有一毛钱关系了)

三、代码说明

  • 我们通过一段go代码来展示,结论是否与上面的分析一致,详细的讲解,都在注释里面了,看懂下面的代码,你会更加了解go这个神奇的语言了。
func exampleFunc(arr []int) {
   arr[0] = 100
   //由于没有超过cap,所以不会生成新的slice
   arr = append(arr, 11111)
}
func main() {
   //创建一个int slice


   arr := make([]int, 2, 5)
   //fill idx
   for i := 0; i < len(arr); i++ {
      arr[i] = i
   }
   //讲arr作为参数,传递到exampleFunc函数中
   exampleFunc(arr)
   for idx := range arr {
      fmt.Printf("idx=%d,value=%d\n", idx, arr[idx])
   }
   //获取slice的data,可以看到,我们在modify中的修改,已经成功了
   //但是由于exampleFunc函数的参数传的是arr的值,所以没法修改len和cap
   //所以你不能够使用for range来进行迭代输出,因为for range只会在 [0-len) 之间迭代
   //我们需要使用一段黑科技了
   hdr := (*reflect.SliceHeader)(unsafe.Pointer(&arr))
   //cast to [cap]int
   data := *(*[5]int)(unsafe.Pointer(hdr.Data))
   //我们可以看到,底层的修改,已经成功了
   fmt.Println(data[2]) //exampleFunc函数扩展的元素,idx = 2
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值