What Causes panic: runtime error: index out of range?
This error occurs when a slice or array index is out of bounds, meaning it is either negative or greater than or equal to the length of the slice or array. Common causes include:
- Accessing indices that do not exist in the slice or array.
- Improper iteration over slices or arrays.
- Assuming slices have a fixed size without checking their length.
- Modifying the length of slices dynamically but not updating access logic.
Common Scenarios and Solutions
1. Accessing an Out-of-Range Index
Attempting to access an index that is beyond the bounds of a slice:
// Incorrect
func main() {
nums := []int{1, 2, 3}
fmt.Println(nums[5]) // panic: runtime error: index out of range
}
Solution: Always check the index against the length of the slice:
// Correct
func main() {
nums := []int{1, 2, 3}
if len(nums) > 5 {
fmt.Println(nums[5])
} else {
fmt.Println('Index out of range')
}
}
2. Improper Iteration
Accessing an index incorrectly during iteration:
// Incorrect
func main() {
nums := []int{1, 2, 3}
for i := 0; i <= len(nums); i++ {
fmt.Println(nums[i]) // panic at i == len(nums)
}
}
Solution: Use proper iteration bounds:
// Correct
func main() {
nums := []int{1, 2, 3}
for i := 0; i < len(nums); i++ {
fmt.Println(nums[i])
}
}
3. Assuming Fixed Slice Size
Assuming a slice has a fixed size without checking its length:
// Incorrect
func main() {
nums := []int{}
fmt.Println(nums[0]) // panic: runtime error: index out of range
}
Solution: Validate the length of the slice before accessing indices:
// Correct
func main() {
nums := []int{}
if len(nums) > 0 {
fmt.Println(nums[0])
} else {
fmt.Println('Slice is empty')
}
}
4. Dynamic Slice Modification
Accessing an index after modifying the slice dynamically:
// Incorrect
func main() {
nums := []int{1, 2, 3}
nums = nums[:2]
fmt.Println(nums[2]) // panic: runtime error: index out of range
}
Solution: Update access logic after modifying the slice:
// Correct
func main() {
nums := []int{1, 2, 3}
nums = nums[:2]
if len(nums) > 2 {
fmt.Println(nums[2])
} else {
fmt.Println('Index out of range after modification')
}
}
Debugging index out of range Errors
- Log Slice Details: Print the length of the slice and the index being accessed:
fmt.Printf('Slice length: %d, Index: %d\n', len(slice), index)
- Use Recover: Handle panics gracefully using Go's
recover
function:
func safeAccess(slice []int, index int) {
defer func() {
if r := recover(); r != nil {
fmt.Println('Recovered from panic:', r)
}
}()
fmt.Println(slice[index])
}
- Inspect Code Logic: Review loops and slice manipulations for potential off-by-one errors.
Best Practices to Avoid index out of range Errors
- Always validate indices against the length of slices or arrays before accessing elements.
- Use Go's range-based loops for safer iteration.
- Write unit tests to cover edge cases involving empty or dynamically modified slices.
- Adopt defensive programming practices to handle empty or short slices.
- Leverage Go's built-in
len()
function to verify slice lengths dynamically.
Conclusion
The panic: runtime error: index out of range
is a common issue in Go programming but can be avoided by following best practices for slice and array access. By understanding its causes and implementing robust debugging strategies, developers can write safer and more reliable Go applications.
FAQs
1. What does panic: runtime error: index out of range mean in Go?
This error occurs when a program attempts to access an element at an index that is out of bounds for a slice or array.
2. How do I fix this error?
Validate the index against the length of the slice or array before accessing it.
3. Can I prevent this error with range-based loops?
Yes, using range-based loops avoids manual index management and helps prevent out-of-range errors.
4. How do I debug index out of range errors in Go?
Log the slice length and index, inspect loops, and use the recover function to handle panics gracefully.
5. Are dynamically modified slices prone to this error?
Yes, dynamically modifying slices can lead to invalid index accesses if the access logic is not updated accordingly.