码迷,mamicode.com
首页 > 其他好文 > 详细

go slice与函数传值的理解

时间:2020-01-18 14:24:16      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:副本   元素   修改   传值   test   行操作   地址   引用类型   进入   

go语言中所有的传值方式都是传值操作。

今天遇到了以下代码:

func main(){
      slice := make([]int ,1,1)
     fmt.Println(slice)
     change(s)
     fmt.Println(slice)  
}

func change(s []int){
     s = append(s,2) 
} 

输出结果是:

    0

    0

当时感到有些疑惑,学c或c++时,传入的参数为指针(数组首地址)时,change内这种直接修改参数s方法时可以修改值的,那么为何在go中无效呢?

1.go语言中,所有的参数传递都是值传递。

什么意思?就是在函数传递值时,都会拷一个副本传递给函数进行操作,就算是引用类型或者指针也不例外。

例如:

func main(){
        st := make([]int, 1, 1)
    fmt.Printf("st 原始切片的地址为:%p\n", &st)
    SliceTest(st)
}

func SliceTest(s []int) {
    fmt.Printf("st 传入后参数s的地址为:%p\n", &s)
    s = append(s, 3)
}

在我的电脑上的输出为:

st 原始切片的地址为:0xc000004540
st 传入后参数s的地址为:0xc000004560

可以看到,go语言中仅仅拷贝了st的一个副本进入SliceTest函数中进行操作,并未操作st本身。

2.go语言的切片,实际上是指向一个底层的数组。

在进入SliceTest函数时,s和st指向的底层数组都一样。

但是,经过append的操作,s原本指向的底层数组不满足追加元素的条件,所以要开辟一个新的数组来进行追加操作。

于是,s会指向一个新的底层数组。

但是这些操作和原切片st完全无关,因为s仅仅是st的副本,它们的地址不一样,s指向了新的数组,st并未改变,所以就有了开篇那段代码的结果。

 

对go的传值理解进一步加深。

go slice与函数传值的理解

标签:副本   元素   修改   传值   test   行操作   地址   引用类型   进入   

原文地址:https://www.cnblogs.com/xuchen950317/p/12208732.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!