How do arrays differ from slices? Can you convert between them?
Question 47MediumGo 1.22 to 1.25
An array's length is part of its type ([4]int and [5]int are different types). An array is a value: assigning it, passing it, or ranging over it copies every element. Arrays are comparable when their element type is, so they can be map keys (for example map[[2]int]bool for grid coordinates). Slices cannot. Arrays with a constant size can live on the stack with no heap allocation.
a := [3]int{1, 2, 3}
b := a // full copy
b[0] = 99
fmt.Println(a, a == [3]int{1, 2, 3}) // [1 2 3] true
s := []int{1, 2, 3, 4}
// Slice -> array pointer (Go 1.17): shares memory
p := (*[4]int)(s)
p[0] = 100
fmt.Println(s[0]) // 100
// Slice -> array (Go 1.20): copies
arr := [4]int(s)
arr[1] = 200
fmt.Println(s[1]) // 2
// Panics at runtime if len(s) < array length
// _ = [8]int(s) // panic: cannot convert slice with length 4 to array or pointer to array with length 8
// Array -> slice
sl := a[:] // shares a's storage
Gotcha: a large array parameter such as func f(buf [1<<20]byte) copies 1 MiB on every call. Pass *[N]T or a slice instead.
More on Arrays, Slices, Maps & Strings
- Q45What is the difference between a nil slice and an empty slice? When does it matter?
- Q46Explain the semantics of the built-in copy. Is it safe with overlapping slices?
- Q48What does this print? (range over an array vs a slice)
- Q49How can subslicing cause memory leaks, and how do you fix them?
- Q50How do you delete elements from a slice efficiently, and what changed with slices.Delete in Go 1.22?
- Q51Why can't you compare slices with ==? How do you check equality of slices, maps, and structs containing them?