将切片附加到函数参数切片

时间:2014-07-18 11:55:22

标签: go

我试图找出切片是如何工作的。请查看以下代码

package main

import "fmt"

type ByteSlice []byte

func (p *ByteSlice) Append(data []byte) {
    slice := *p
    *p = append(slice, data...)
}

func main() {
    var a ByteSlice
    a[0] = 3
    b := []byte{4,6,7}
    a.Append(b)
    fmt.Println(b)
}

正如你在append函数中看到的那样,我尝试将slice参数追加到调用中,但是我遇到了以下错误:

panic: runtime error: index out of range

goroutine 16 [running]:
runtime.panic(0x4a14e0, 0x51333c)
    c:/go/src/pkg/runtime/panic.c:279 +0xe9
main.main()
    D:/Go/samples/src/method.go:16 +0x243

goroutine 17 [runnable]:
runtime.MHeap_Scavenger()
    c:/go/src/pkg/runtime/mheap.c:507
runtime.goexit()
    c:/go/src/pkg/runtime/proc.c:1445

goroutine 18 [runnable]:
bgsweep()
    c:/go/src/pkg/runtime/mgc0.c:1976
runtime.goexit()
    c:/go/src/pkg/runtime/proc.c:1445

goroutine 19 [runnable]:
runfinq()
    c:/go/src/pkg/runtime/mgc0.c:2606
runtime.goexit()
    c:/go/src/pkg/runtime/proc.c:1445
exit status 2

我错在哪里?

2 个答案:

答案 0 :(得分:9)

逐行查看我的评论:

切片只是一个"视图"一个数组。

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

package main

import "fmt"

type ByteSlice []byte

func (p *ByteSlice) Append(data []byte) {
    *p = append(*p, data...)
}

func main() {
    var a ByteSlice // is just a pointer
    // a[0] = 3  does not have memory allocate
    a = append(a, 3) // append allocates a memory underneath
    fmt.Println(a[0])
    b := []byte{4, 6, 7}
    a.Append(b)
    fmt.Println(a)
}

输出

3 [3 4 6 7]

答案 1 :(得分:3)

为了澄清其他答案,错误是您尝试分配a[0]的结果。

要了解原因,首先需要了解切片的解剖结构。切片由三个字段组成:

  • 其长度(您在切片中指定的元素数量)
  • 其容量(基础数组的实际大小,可以调整大小)
  • 指向基础数组的指针。

因为切片仅在逻辑上包含长度字段指定的元素数,所以您只能访问切片的那么多元素。您可以访问切片的未定义元素,就像使用C中的数组一样,这是一个安全功能。

初始化切片时,除非包含初始化元素或另行指定,否则它的长度为0。你没有做过,因此a[0]超出了范围。您必须使用append - a = append(a, 3),特别是 - 将a的第一个元素指定给3

Go blog post that more fully discusses this

另外,正如@fabrizioM所指出的,没有必要在slice中声明ByteSlice.Append变量;你可以使用*p