panic: runtime error: index out of range
panic: runtime error: index out of range [5] with length 3Программа обратилась к элементу среза, массива или строки по номеру, которого нет, и аварийно остановилась — в Go это называется паникой (panic). В квадратных скобках — индекс, к которому обратились (5), дальше — длина (3). Допустимые индексы — от 0 до len-1, то есть здесь 0, 1 и 2. Под сообщением Go печатает стек — цепочку вызовов, которая привела к ошибке: найдите первую строку с файлом своей программы — там и ошибка.
Частые причины
<= вместо < в цикле.
for i := 0; i <= len(s); i++ {
fmt.Println(s[i]) // на последнем шаге i == len(s) — такого элемента нет
}Правильно — i < len(s), а ещё надёжнее for i := range s: так индекс никогда не выйдет за границы.
Пустой срез. s[0] у пустого среза — уже выход за границы: index out of range [0] with length 0. Перед обращением проверьте длину:
if len(s) > 0 {
fmt.Println(s[0])
}make с длиной 0. make([]int, 0, 10) создаёт пустой срез с запасом места: s[0] = 1 вызовет панику. Либо добавляйте элементы через append, либо создайте срез нужной длины — make([]int, 10).
Аргументы командной строки. os.Args[0] — имя программы, аргументы начинаются с os.Args[1]. Если запустить программу без аргументов, os.Args[1] даст index out of range [1] with length 1:
package main
import (
"fmt"
"os"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("укажите имя: go run . Анна")
return
}
fmt.Println("Привет,", os.Args[1])
}Индекс посчитан с ошибкой. s[len(s)] вместо s[len(s)-1] для последнего элемента, s[i+1] на последнем шаге цикла. Проверьте крайние значения: первый и последний шаг.
Строки. Индекс строки — номер байта, а не буквы: в "мир" три буквы, но шесть байт, и s[3] — второй байт буквы «и», а не третья буква. Для работы с буквами переведите строку в []rune(s).
slice bounds out of range
panic: runtime error: slice bounds out of range [:5] with capacity 3То же, но при взятии части s[a:b]: правая граница больше, чем позволяет срез, или левая больше правой (slice bounds out of range [3:2]). Проверьте a <= b и b <= len(s) перед тем, как брать часть.
Компилятор ловит часть ошибок сам
Если индекс — постоянное число, а длина известна заранее (массив [3]int или строка-константа), программа с a[5] даже не соберётся: компилятор сообщит, что индекс вне границ. Для срезов длина известна только при работе программы, поэтому там ошибка видна лишь при запуске.
Как не падать
Паника — признак ошибки в программе, а не способ обработки данных. Проверяйте длину до обращения (if i < len(s)) и возвращайте error, если данные от пользователя неполные. Перехватывать такую панику через recover можно (defer), но это маскирует ошибку, а не исправляет её.