Slices, maps and strings · 3 MIN READ
len is what you may read; cap is what you may reslice
Say which of two similar-looking index expressions panics.
A slice has both a length and a capacity, and they gate different things. Indexing is checked against len: s[i] panics the moment i reaches len, however much capacity remains behind it. Reslicing is checked against cap: s[:n] is legal for any n up to cap, and that is how a slice grows back into space it had already allocated.
This is why make([]int, 0, 10) is not indexable at all and make([]int, 10) is: the first has room for ten and holds none.
SEE THE IDEA
Indexing and reslicing use different limits
- 01
Index
gos[i]Requires 0 ≤ i < len(s)
- 02
Reslice
gos[:n]May extend up to cap(s)
- 03
Full slice
gos[:n:n]Also limits future append capacity
Both operations are checked; capacity is not an indexing permission.
In practice
Check bounds at the boundary where external indexes enter your program. A sub-slice capacity starts at its own first element, not at the original array beginning. A full slice expression is useful when passing a view to code that may append without permission to overwrite later elements.
Watch out
Restricting capacity prevents append from using later storage; it does not prevent writes to elements already in the view.
Read and predict
package main
import "fmt"
func main() {
s := make([]int, 3, 8)
fmt.Println(len(s), cap(s))
grown := s[:6]
fmt.Println(len(grown), cap(grown))
defer func() {
if r := recover(); r != nil {
fmt.Println("panic on index")
}
}()
fmt.Println(s[5])
}What does this print?
Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.
Progress stays in this browser. No account needed.