如何在golang中更改指针切片

时间:2015-03-29 22:37:11

标签: go

我正在努力更好地了解go。我为自己创建了一个小练习:将指针切片传递给函数并修改它。

这就是我提出的:

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    var data *[]byte
    fillData(data)
    fmt.Println((*data)[0:5])
}

func fillData(data *[]byte) {
    b := []byte("hello")
    fmt.Println(b[0:5])
    fmt.Println(string(b[0:5]))
    data = (*[]byte)(unsafe.Pointer(&b[0]))
}

但它会出现invalid memory address or nil pointer dereference错误。我知道我不会在实际代码中使用这样的东西,但我很好奇如何传递切片并修改它而不返回它。

https://play.golang.org/p/_K5ltKKKNV

1 个答案:

答案 0 :(得分:3)

当您尝试更新data中的fillData时,会出现两个错误。首先,更新指针而不是它指向的指针。其次,data是一个nil指针,因此通过该指针写入将导致nil指针错误。

这是编写代码的一种可能方式。 data以零切片开头,并在fillData内更新。这会将切片信息(len,cap和指向数组的指针)从b复制到*data,这意味着data将与b共享信息(重要的是,包括共享)底层数组)。

package main

import "fmt"

func main() {
    var data []byte
    fillData(&data)
    fmt.Println(data, data[0:5])
}

func fillData(data *[]byte) {
    b := []byte("hello")
    *data = b[0:1]
}

另一种方法是让data成为指针并更新它。然后你必须将双指针传递给fillData。这看起来像这样:

package main

import "fmt"

func main() {
    var data *[]byte
    fillData(&data)
    fmt.Println((*data)[0:5])
}

func fillData(data **[]byte) {
    b := []byte("hello")
    *data = &b
}

最后,编写此代码的最佳方法是根本不使用指针,只返回切片。与C或C ++不同,它很少需要使用"输出"函数的参数。这是因为go允许多个返回值。

package main

import "fmt"

func main() {
    data := getData()
    fmt.Println(data, data[0:5])
}

func getData() []byte {
    return []byte("hello")[:1]
}