# How to get the backing array of a slice

Published Mon 31 Jul, 2023

Before Go 1.17 it was not possible to get a reference to the backing array of a slice without resorting to the `reflect` and `unsafe` packages to inspect the raw slice header. Not ideal.

Some resources refer to "backing array" as the "underlying array". These are the same thing.

However, since 1.17 it is possible to convert a slice to a pointer to an array using a type conversion:

``````a1 := string{"👁", "👃", "👁"}
s := a1[:]
a2 := (*string)(s)
``````

In the example above, `a2` will be equal to the memory address of `a1`. In other words, `&a1 == a2` is true.

If we diagram the situation it looks like this: Converting s to a *string gives us a new reference to a1.

There are some limits you should be aware of.

### Limit 1: Length of slice

The length of the array can not be greater than the length of the slice, even if the backing array has more capacity.

``````a1 := string{"👁", "👃", "👁"}
s := a1[:2] // get a slice of len 2
a2 := (*string)(s) // will panic!
``````

The above example will panic. We can’t convert a slice of length 2 to a pointer to an array of length 3.

### Limit 2: Begins at slice offset

The pointer to the array will always start at the beginning of the slice. If your slice does not start at the beginning of its backing array your array pointer will not do so either.

``````a1 := string{"👁", "👃", "👁"}
s := a1[1:] // get a slice of len 2 with offset 1
a2 := (*string)(s)
``````

Since slice `s` has a length of 2 we can only convert to a `*string`.

We will not be able to get a reference to the `a1` element. The diagram below illustrates this. Results in a situation where we can't access a1 via the new reference.

## Reference to the full backing array

Put together, these limits mean that you can only get an array that references the “window” of any specific slice.

If you want a reference to the full backing array of a slice you will need to know how it was created:

• Created via `make`, a literal or returned from `append`: The slice will always start at the first element, so you can re-slice up to its capacity and get a reference to the entire backing array.
• Created via slicing of an array: You will already have the full array reference.
• Created via re-slicing: Find out how the original slice was created, if it was also re-sliced, follow the originals until you find a non re-sliced slice.

## Copy slice to array (1.20 and later)

Since Go 1.20 you also have the option to directly convert slices to new arrays, no pointers required. The limits above regarding the “window” still apply.

``````a1 := string{"👁", "👃", "👁"}
s := a1[:]
a2 := string(s)
``````

In the above example `a2` will be a new array containing the same values as `a1`. Converting s to a string gives us a copy of a1.

Run the code below to see the differences between the two conversions.

main.go
``````package main

import (
"fmt"
)

func main() {
original := string{"👁", "👃", "👁"}
s := original[:]
ptr := (*string)(s)
cpy := string(s)

fmt.Printf("&original: %p\n", &original)
fmt.Printf("ptr: %p\n", ptr)
fmt.Printf("&cpy: %p\n", &cpy)
fmt.Printf("ptr == &original: %v\n", ptr == &original)
fmt.Printf("&cpy == &original: %v\n", &cpy == &original)
}
``````

## Stay in the loop,subscribe to my newsletter.

``````for _, f := range []string{
"🏋 Excercises and solutions",
"🔥 Subscriber-only content",
"💌 New posts in your inbox",
"💸 Discounts",
} {
you.Enjoy(f)
}
``````