duanheyi7147 2018-09-29 06:02
浏览 19
已采纳

无法在函数内附加到切片[重复]

This question already has an answer here:

I tried to add an element to my slice inside a function. I can change the element of the slice but cannot add a new element to it. Since slices act like reference why can't I change it?

Below is the code I have tried:

package main

import (
    "fmt"
)

func main() {
    a := []int{1, 2, 3}
    change(a)
    fmt.Println(a)
}
func change(a []int) {
    a[0] = 4
    a = append(a, 5)
}
</div>
  • 写回答

1条回答 默认 最新

  • dongxiaoxiao1983 2018-09-29 06:08
    关注

    Slice are pointers to underlying array. It is described in Golang:

    Map and slice values behave like pointers: they are descriptors that contain pointers to the underlying map or slice data. Copying a map or slice value doesn't copy the data it points to. Copying an interface value makes a copy of the thing stored in the interface value. If the interface value holds a struct, copying the interface value makes a copy of the struct. If the interface value holds a pointer, copying the interface value makes a copy of the pointer, but again not the data it points to.

    you are passing a copy of the slice not the original slice. Return the value after appending to the slice and then assign it to the original slice as

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        a := []int{1, 2, 3}
        a = change(a)
        fmt.Println(a)
    }
    
    func change(a []int) []int{
        a = append(a, 5)
        return a
    }
    

    Playground Example

    Or you can pass a pointer to slice of int but it is not recommended since slice it self is a pointer to bootstrap array.

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        a := []int{1, 2, 3}
        change(&a)
        fmt.Println(a)
    }
    
    func change(a *[]int){
        *a = append(*a, 5)
    }
    

    Note: Everything in Golang is pass by value.

    One thing to be considered is even if you are returning the updated slice and assigning to the same value, its original len and cap will change, which will lead to a new underlying array of different len. Try to print the length and cap before and after changing the slice to see the difference.

    fmt.Println(len(a), cap(a))
    

    The length is the number of elements referred to by the slice. The capacity is the number of elements in the underlying array (beginning at the element referred to by the slice pointer).

    Since the underlying array will check you can check it using reflect and unsafe for fetching the underlying array which is going to be different if cap of a slice change after appending data which is your case.

    package main
    
    import (
        "fmt"
        "reflect"
        "unsafe"
    )
    
    func main() {
        a := []int{1, 2, 3}
        hdr := (*reflect.SliceHeader)(unsafe.Pointer(&a))
        data := *(*[3]int)(unsafe.Pointer(hdr.Data))
        fmt.Println(data)
        a = change(a)
        hdr = (*reflect.SliceHeader)(unsafe.Pointer(&a))
        newData := *(*[4]int)(unsafe.Pointer(hdr.Data))
        fmt.Println(newData)
    }
    
    func change(a []int) []int {
        a = append(a, 5)
        return a
    }
    

    Playground Example

    This is the best part of slices that you need to worry about its capacity when appending data more than its capacity, since it will point to a new array allocated in the memory of bigger length.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 自适应 LMS 算法实现 FIR 最佳维纳滤波器matlab方案
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥15 Python3.5 相关代码写作
  • ¥20 测距传感器数据手册i2c
  • ¥15 RPA正常跑,cmd输入cookies跑不出来
  • ¥15 求帮我调试一下freefem代码
  • ¥15 matlab代码解决,怎么运行
  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像