pani c: ошибка времени выполнения: индекс выходит за пределы диапазона [0] с длиной 0 - PullRequest
0 голосов
/ 13 апреля 2020

Для приведенного ниже кода:

func Insert(m []Bucket, key string, value float64) {

    bucketNumber := (key[0] - 'A') / 7

    if cap(m[bucketNumber]) == 0 {
        m[bucketNumber] = make([]Entry, 0, 100)
    }

    var bucketFull bool
    bucketFull = len(m[bucketNumber]) == cap(m[bucketNumber])

    if bucketFull {

        m[bucketNumber] = append(m[bucketNumber], Entry{key, value})
    } else {

        m[bucketNumber][emptyPosition[bucketNumber]] = Entry{key, value}
    }
    emptyPosition[bucketNumber]++
}

m[bucketNumber][emptyPosition[bucketNumber]] = Entry{key, value} выдает ошибку

pani c: ошибка времени выполнения: индекс выходит за пределы диапазона [0] с длина 0`

несмотря на m[bucketNumber] = make([]Entry, 0, 100)

Почему назначение не выполняется с ошибкой во время выполнения?

1 Ответ

2 голосов
/ 13 апреля 2020

make([]Entry, 0, 100) создает фрагмент, который будет иметь длину 0 и емкость 100. Индекс должен быть меньше длины.

Так, если длина равна 0, четный индекс 0 выходит за пределы диапазон.

Если вы хотите создать срез из 100 элементов, используйте

make([]Entry, 100, 100)

Или просто

make([]Entry, 100)

Третий параметр - емкость - используется для уменьшите будущие выделения при добавлении элементов к слайсу.

Если вы хотите создать свой слайс с длиной 0, используйте встроенную функцию append() для добавления элементов к слайсу, например:

s := make([]int, 0, 10)
s = append(s, 1)

Ваша конкретная проблема c:

bucketFull = len(m[bucketNumber]) == cap(m[bucketNumber])

Это только проверяет, равна ли длина емкости. Для вновь выделенного среза (с make([]Entry, 0, 100)) это, очевидно, будет false (0 не равно 100), но это не означает, что вы можете назначить элемент среза. Как уже упоминалось, индекс должен быть меньше длины.

Это свойство bucketFull сообщает только о том, можно ли добавить новый элемент в срез без перераспределения. Добавление нового элемента может быть достигнуто с помощью встроенного append(), или среза среза с использованием встроенного append() или с выражением среза.

Читайте сообщения блога, чтобы узнать фрагменты и массивы:

Блог Go: Go Срезы: использование и внутренние компоненты

Блог Go: массивы, срезы (и строки): Механика 'append «

...