megakor
@megakor
Go/PHP developer | ВКонтакте

Многократное использование len() или кеширование в переменную?

IDE во многих других языках типа PHP подсказывает, что не стоит использовать len() (или аналогичные функции) в конструкции for, так как при каждой итерации будет заново вычисляться длина массива.

Я проверил, что если вместо len вставить свою функцию, которая что-то выводит, то она выполнится при каждом цикле:

kek := func() int {
    fmt.Prinln("CALL")
    return 10
}

for i := 0; i < kek(); i++ {
    //
}


В примере выше строка "CALL" будет выведена на экран 10 раз.

В Go тоже лучше переносить такие вещи в переменные?

Данный код идентичен по производительности или второй вариант предпочтительнее?

// 1:
for i := 0; i < len(data); i++ {
    //
}

// 2:
dataLength := len(data)
for i := 0; i < dataLength; i++ {
    //
}


На самом деле, вроде как ни разу не видел (даже в официальной песочнице) чтобы это переносили в переменную выше цикла, len() что - кешируется?
  • Вопрос задан
  • 233 просмотра
Решения вопроса 2
С помощью этой штуки можно посмотреть, во что это компилируется: https://github.com/badamczewski/PowerUp

Но вообще len должен просто возвращать длину слайса, которая записана в поле, по тому большой разницы не будет.
Если у тебя действительно, внутри цикла не может измениться слайс - можно закэшировать.
Если может измениться - кэшировать не следует.
Ответ написан
WinPooh32
@WinPooh32
Stack Overflow answer searching expert
Дескриптор у слайса имеет такую структуру:
type SliceHeader struct {
        Pointer uintptr
        Len  int
        Cap  int
}


len(...) - это ключевое слово языка и в контексте компилятора не является функцией, вместо которой он может подставить что угодно.

Выше мы выяснили, что у слайса есть поле с длиной, соответственно нет смысла кешировать длину в отдельной переменной. Т.к. компилятор просто заменит вызов len на обращение к полю в дескрипторе слайса. Он вообще может переместить длину в регистр процессора и не обращаться к ram при итерации.

Если нужно экономить ресурсы, то лучше подумайте о неявной проверке на выход за границы массива, которая в некоторых случая может сожрать нехилую часть процессорного времени. Подробнее прочитать можно в этой статье.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
uvelichitel
@uvelichitel Куратор тега Go
habrahabr.ru/users/uvelichitel
А зачем вообще может понадобиться такая конструкция когда есть встроенный оператор
for i:= range data {}
компактно и идиоматично
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы