Поведение добавления при добавлении элемента к фрагменту максимального размера - PullRequest
0 голосов
/ 12 декабря 2018

Меня смущает поведение при добавлении к срезу, который уже имеет максимально возможный размер.

Насколько я понимаю, срез может иметь максимальный размер int32 или int64 в зависимости от вашегоsystem.

При выполнении test := make([]struct{},math.MaxInt64+1) я получаю ошибку len argument too large in make([]struct {}), что соответствует моим ожиданиям.Но когда я делаю что-то вроде:

test := make([]struct{},math.MaxInt64)
for i:=0;i<100 ; i++ {
    test = append(test, struct{}{})
}
fmt.Println(len(test))

Я ожидаю, что программа запаникует, но на удивление код работает без проблем и len возвращает переполненное значение с -9223372036854775709.

Couldкто-то может проработать поведение?

(я использую go1.11.2 linux / amd64)

1 Ответ

0 голосов
/ 12 декабря 2018

В спецификации говорится о длине и емкости любого среза:

В любое время выполняется следующее соотношение:

0 <= len(s) <= cap(s)

Этоявно нарушается, так как длина становится отрицательной, и, следовательно, меньше 0. Так что это ошибка, о которой уже сообщалось, и прогресс можно отследить здесь: https://github.com/golang/go/issues/29190

Ян Лэнс Тейлор подтверждает, что это ошибка ине так, как это должно работать.Правильным поведением было бы паническое высказывание growslice: cap out of range, которое должно происходить из функции slice.go / growslice() (growslice() вызывается из append()).

Если мы немного изменим ваш примерна это:

s := make([]struct{}, math.MaxInt32-2)
fmt.Println(len(s), cap(s))
for i := 0; i < 5; i++ {
    s = append(s, struct{}{})
    fmt.Println(len(s), cap(s))
}

И запустить его на Go Playground :

2147483645 2147483645
2147483646 2147483646
2147483647 2147483647
-2147483648 2147483647
-2147483647 2147483647
-2147483646 2147483647

Как мы видим, емкость перестает расти, как только она достигает MaxInt32на 32-разрядных архитектурах и MaxInt64 на 64-разрядных архитектурах.

...