将切片从功能参数追加到切片

I am trying to find out, how slice works. Look at the following code

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

As you can see in the append function, i try to append slice parameter into call but i've got the following error:

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

What do i here wrong?

See my comments line by line:

a slice is just a "view" of an array.

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

output

3 [3 4 6 7]

To clarify the other answer, the error is a result of your attempt to assign a[0].

To understand why, you first need to understand the anatomy of a slice. A slice consists of three fields:

  • Its length (the number of elements you've assigned in the slice)
  • Its capacity (the actual size of the underlying array, which can be resized)
  • A pointer to the underlying array.

Because the slice only logically contains the number of elements specified by the length field, you can only access that many elements of the slice. The fact that you can't access undefined elements of the slice, like you can with an array in C, is a safety feature.

When you initialize a slice, it's length is 0 unless you include initialization elements or specify otherwise. You did neither, and a[0] is therefore out of range. You'd have to use append - a = append(a, 3), specifically - to assign the first element of a to 3.

There's a Go blog post that more fully discusses this.

Also, as @fabrizioM pointed out, there's no need to declare the slice variable in ByteSlice.Append; you can just use *p.