Are slices passed by value?

Everything in Go is passed by value, slices too. But a slice value is a header, describing a contiguous section of a backing array, and a slice value only contains a pointer to the array where the elements are actually stored. The slice value does not include its elements (unlike arrays).

So when you pass a slice to a function, a copy will be made from this header, including the pointer, which will point to the same backing array. Modifying the elements of the slice implies modifying the elements of the backing array, and so all slices which share the same backing array will “observe” the change.

To see what’s in a slice header, check out the reflect.SliceHeader type:

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

See related / possible duplicate question:
Performance of function slice parameter vs global variable?

Read blog post: Go Slices: usage and internals

Please note that when you pass a slice to a function, if the function modifies the “existing” elements of the slice, the caller will see / observe the changes. If the function adds new elements to the slice, that requires changing the slice header (the length at a minimum, but may also involve allocating a new backing array), which the caller will not see (not without returning the new slice header).

Not with maps, because maps are pointers under the hood, and if you pass a map to a function and the function adds a new entry to the map, the map pointer will not change so the caller will see the changed map (the new entry) without returning the map after change.

Also regarding slices and maps, see Map initialization in Go and why slice values can sometimes go stale but never map values?

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)