golang 切片传参

切片的底层是三个值

  • 指向底层数组首地址的指针
  • Len
  • Cap

所以对于以下代码

package main

import (
   "fmt"
   "time"
)

func f(slice []int, ch chan int) {
   slice[0] = 2
   ch <- 1
   for i := 0; i < 10; i++ {
      slice = append(slice, 4)
   }
   ch <- 2
   slice[0] = 3
   ch <- 3
}

func main() {
   slice := []int{1, 2, 3}
   ch := make(chan int)
   go f(slice, ch)
   _ = <-ch
   fmt.Println(slice) // 2 2 3
   _ = <-ch
   fmt.Println(slice) // 2 2 3
   _ = <-ch
   fmt.Println(slice) // 2 2 3
   time.Sleep(1)
}

看懂这个代码首先要知道go语言的赋值都是“值语义”的,也就是所有赋值本质都是拷贝了一份副本,不存在传引用的情况。

  • 因为是值语义,所以形参实际是拷贝的副本,但底层指针指向的数组地址是同一个(但是指针变量本身的地址不是同一个,相当于两个指针指向了一个地址)
  • 所以一开始改第一个数的时候,实参是感受的,因为底层数组是同一个
  • 但是往后推一个数时,虽然底层数组也推了一个数,但函数中的len+1函数外不感受(len是拷贝的副本,函数里改了函数外不会改),所以结果还是2 2 3
  • 当往后推的数到扩容时,形参的指针会指向另一个底层数组,此时再改第一个数函数外的也不感受了。

因此建议函数更改切片这种场景,直接返回改过的切片,不要依赖参数去改

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值