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:
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
.