What happens if I return a slice of an array that is a local variable of a function or method? Does Go copy the array data into a slice create with make()
? Will the capacity match the slice size or the array size?
func foo() []uint64 {
var tmp [100]uint64
end := 0
...
for ... {
...
tmp[end] = uint64(...)
end++
...
}
...
return tmp[:end]
}
This is detailed in Spec: Slice expressions.
The array will not be copied, but instead the result of the slice expression will be a slice that refers to the array. In Go it is perfectly safe to return local variables or their addresses from functions or methods, the Go compiler performs an escape analysis to determine if a value may escape the function, and if so (or rather if it can't prove that a value may not escape), it allocates it on the heap so it will be available after the function returns.
The slice expression:
tmp[:end]
meanstmp[0:end]
(because a missinglow
index defaults to zero). Since you didn't specify the capacity, it will default tolen(tmp) - 0
which islen(tmp)
which is100
.You can also control the result slice's capacity by using a full slice expression, which has the form:
Which sets the resulting slice's capacity to
max - low
.More examples to clarify the resulting slice's length and capacity:
Try it on the Go Playground.
Avoiding heap allocation
If you want to allocate it on the stack, you can't return any value that points to it (or parts of it). If it would be allocated on the stack, there would be no guarantee that after returning it remains available.
A possible solution to this would be to pass a pointer to an array as an argument to the function (and you may return a slice designating the useful part that the function filled), e.g.:
If the caller function creates the array (on the stack), this will not cause a "reallocation" or "moving" to the heap:
Running
go run -gcflags '-m -l' play.go
, the result is:The variable
tmp
is not moved to heap.Note that
[100]uint64
is considered a small array to be allocated on the stack. For details see What is considered "small" object in Go regarding stack allocation?Nothing wrong happens.
Go does not make a copy but compiler performs escape analysis and allocates the variable that will be visible outside function on heap.
The capacity will be the capacity of underlying array.
The data is not copied. The array will be used as the underlying array of the slice.
It looks like you're worrying about the life time of the array, but the compiler and garbage collector will figure that out for you. It's as safe as returning pointers to "local variables".