Pointers 无法附加到函数内的切片

Pointers 无法附加到函数内的切片,pointers,go,slice,Pointers,Go,Slice,我试图在函数内的切片中添加一个元素。我可以更改切片的元素,但不能向其添加新元素。既然切片的行为类似于引用,为什么我不能更改它 以下是我尝试过的代码: 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) } 切片是指向底

我试图在函数内的切片中添加一个元素。我可以更改切片的元素,但不能向其添加新元素。既然切片的行为类似于引用,为什么我不能更改它

以下是我尝试过的代码:

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)
}

切片是指向底层数组的指针。在Golang中有描述:

映射和切片值的行为类似于指针:它们是 包含指向基础映射或切片数据的指针。复制地图或 切片值不会复制它指向的数据。复制接口 值生成存储在接口值中的对象的副本。如果 接口值保存一个结构,复制接口值会生成一个 结构的副本。如果接口值包含指针,则复制 接口值生成指针的副本,但同样不是指针的副本 它指向的数据

您传递的是切片的副本,而不是原始切片。在附加到切片后返回值,然后将其指定给原始切片作为

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
}

也可以将指针传递给int的slice,但不建议这样做,因为slice本身就是指向引导数组的指针

package main

import (
    "fmt"
)

func main() {
    a := []int{1, 2, 3}
    change(&a)
    fmt.Println(a)
}

func change(a *[]int){
    *a = append(*a, 5)
}
注意:戈兰的一切都是按价值传递的

需要考虑的一件事是,即使返回更新的切片并将其赋值给相同的值,其原始len和cap也会发生变化,这将导致不同len的新底层数组。尝试在更改切片前后打印长度和封口,以查看差异

fmt.Println(len(a), cap(a))
长度是切片引用的元素数。容量是基础数组中的元素数(从切片指针引用的元素开始)

由于基础数组将进行检查,因此您可以使用reflect和unsafe来检查它,以获取基础数组。如果在添加数据(即您的情况)后切片的上限发生变化,则基础数组将不同

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
}


这是切片中最好的部分,当追加的数据超过其容量时,您需要担心它的容量,因为它将指向在内存中分配的更大长度的新数组。

为此,您需要在change函数中返回a,并将其分配给main`a=change(a)`中的a,或者通过引用传递一个
func change(a*[]int)
go中按值传递的结构。谢谢,已工作,这意味着我可以使用切片引用更新字段?您可以更新切片中的元素,而无需逐个引用传递切片,但您不能修改切片本身(长度和容量),以更好地了解切片的工作方式