Appending to a slice of an array on the stack

74 views
Skip to first unread message

Miguel D

unread,
Apr 18, 2020, 1:26:11 PM4/18/20
to golang-nuts
Hello everyone.
I'm learning the go language and I have some questions regarding the implementation of slices.

$ cat slice_stack.go
package main

import "fmt"

func main
() {
    stack_array
:= [4]int{1,2,3,4}
   
// !- I assume this is on the stack, like a local int[4] would be in C.

    slice
:= stack_array[:] // Does this copy the data to the heap?
                           
// or just get a slice to the mem on the stack?
   
for i := 0; i<25; i++ {
        slice
= append(slice, 99) // Does this copy the data to the heap on first append?
   
}

    fmt
.Println(stack_array)
    fmt
.Println(slice)
}


$ go run slice_stack.go
[1 2 3 4]
[1 2 3 4 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99]

Is it common to get slices to arrays on the stack? Am I wrong when I say stack_array is on the stack?
Thank you.

Marcin Romaszewicz

unread,
Apr 18, 2020, 3:19:31 PM4/18/20
to Miguel D, golang-nuts
I added a little more to your example to illustrate my email points.

1) stack_array may or may not be on the stack, Go makes that choice.

2) slice := stack_array[:] Doesn't copy the data, it creates a slice structure which wraps it.

3) Next, when you call slice = append(slice, 99), Go will allocate a new backing buffer and copy the initial four values. Now you have a copy. "slice".

A slice is just this struct:
https://golang.org/src/runtime/slice.go

type slice struct {
    14  	array unsafe.Pointer
    15  	len   int
    16  	cap   int
    17  }

When you create your initial slice, you get array = stack_array, len = 4, cap = 4.

When you append the next element, you get
array = <new array>, len=5, cap=5. The first 4 elements will have been copied.

-- Marcin

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/221259d6-8cd2-4f51-b67d-757a0f802e7b%40googlegroups.com.

Brian Candler

unread,
Apr 18, 2020, 3:50:47 PM4/18/20
to golang-nuts
And very nice explanation here:

Ian Lance Taylor

unread,
Apr 18, 2020, 4:23:56 PM4/18/20
to Miguel D, golang-nuts
On Sat, Apr 18, 2020 at 10:26 AM Miguel D <david.ho...@gmail.com> wrote:
>
Besides what other people said, I want to clarify that whether a value
is on the stack or the heap is not a property of the language.
Different implementations of Go can and do make different choices in
this area.

For the gc compiler that most people use, you can get information
about whether a value is on the stack or the heap by using
"-gcflags=-m". For your example that prints

# command-line-arguments
foo.go:15:16: inlining call to fmt.Println
foo.go:16:16: inlining call to fmt.Println
foo.go:6:5: moved to heap: stack_array
foo.go:15:16: stack_array escapes to heap
foo.go:15:16: []interface {} literal does not escape
foo.go:16:16: slice escapes to heap
foo.go:16:16: []interface {} literal does not escape
<autogenerated>:1: .this does not escape

So at present stack_array does escape to the heap. That may change in
future releases.

You can get a bunch more info using -gcflags=-m=2.

Ian
Reply all
Reply to author
Forward
0 new messages