Panic: runtime error: makeslice: cap out of range — Почему это происходит и как это исправить

Скорее всего, вы уже сталкивались с panic: runtime error: makeslice: cap out of range. Эта ошибка, как правило, возникает при работе со слайсами, и сегодня мы разберемся, почему она появляется и как ее избежать.

Суть проблемы: длина и емкость слайса

В Go слайс — это динамический массив, который ссылается на часть базового массива. У слайса есть два ключевых параметра:

  • Длина (length): Количество элементов, которые слайс содержит.
  • Емкость (capacity): Количество элементов, которые могут быть размещены в базовом массиве без перераспределения памяти.

И вот тут кроется главная причина ошибки: длина слайса всегда должна быть меньше или равна его емкости. Ссылка на оф. документацию

Почему возникает panic: runtime error: makeslice: cap out of range?

Эта ошибка возникает, когда вы пытаетесь создать слайс, у которого емкость меньше, чем длина. Проще говоря, вы говорите Go: «Я хочу слайс, который содержит 10 элементов, но у него есть место только для 5». Go, естественно, не может этого сделать и вызывает панику.

Пример, который вызывает ошибку:

Go

package main

import "fmt"

func main() {
        // Пытаемся создать слайс с длиной 10 и емкостью 5.
        k := make([]int, 10, 5)
        fmt.Println(k)
}

При запуске этого кода вы увидите:

panic: runtime error: makeslice: cap out of range

Почему это не ошибка компиляции?

Вы могли бы подумать: «Почему компилятор не обнаруживает эту ошибку?» Дело в том, что значения длины и емкости слайса могут быть определены во время выполнения программы.

Пример, когда значения определяются во время выполнения:

Go

package main

import (
        "fmt"
        "math/rand"
        "time"
)

func main() {
        rand.Seed(time.Now().UnixNano())
        length := rand.Intn(10) // Случайная длина
        capacity := rand.Intn(5) // Случайная емкость

        // Ошибка может возникнуть, если length > capacity.
        k := make([]int, length, capacity)
        fmt.Println(k)
}

В этом примере значения length и capacity определяются случайным образом во время выполнения. Компилятор не может предсказать, будут ли они корректными.

Как избежать ошибки?

  1. Всегда проверяйте, что длина меньше или равна емкости. Если вы получаете значения длины и емкости из внешних источников, убедитесь, что они соответствуют этому правилу.
  2. Используйте append для добавления элементов. Если вы не знаете заранее, сколько элементов будет в слайсе, используйте функцию append. Она автоматически увеличивает емкость слайса, если это необходимо.
  3. Если вы знаете только длину, не указывайте емкость. Если вы знаете только длину слайса, не указывайте емкость. Go автоматически установит емкость равной длине.

Пример правильного использования append:

package main

import "fmt"

func main() {
        k := make([]int, 0, 5) // Создаем слайс с длиной 0 и емкостью 5.

        for i := 0; i < 10; i++ {
                k = append(k, i) // Добавляем элементы.
        }

        fmt.Println(k)
}

В этом примере мы создаем слайс с длиной 0 и емкостью 5. Затем мы добавляем 10 элементов с помощью append. Go автоматически увеличивает емкость слайса, когда это необходимо.

Вывод

panic: runtime error: makeslice: cap out of range — это распространенная ошибка, которая возникает, когда вы пытаетесь создать слайс с емкостью, меньшей, чем его длина. Всегда помните, что 0 <= len(s) <= cap(s). Используйте append для динамического добавления элементов и проверяйте значения длины и емкости, если они определяются во время выполнения.

Надеюсь, эта статья помогла вам разобраться с этой ошибкой.

Рекомендуем к прочтению



Оставить комментарий

Этот сайт защищен reCAPTCHA и применяются Политика конфиденциальности и Условия обслуживания применять.

Срок проверки reCAPTCHA истек. Перезагрузите страницу.