Ответ
В Go len() — это не обычная функция, а встроенная конструкция языка, которая обрабатывается компилятором особым образом. Она возвращает длину для коллекций нескольких типов.
Производительность и сложность: O(1)
Вызов len() всегда выполняется за константное время O(1). Это возможно, потому что длина является неотъемлемой частью внутренней структуры данных и хранится в ней явно. len() просто читает это готовое значение.
- Слайс (Slice): Структура слайса в памяти (slice header) содержит три поля: указатель на нижележащий массив, длину (
len) и ёмкость (cap).len(mySlice)— это прямое чтение поляlen.// Внутреннее представление слайса type sliceHeader struct { Data uintptr Len int Cap int } - Строка (String): Строка, как и слайс, имеет заголовок с указателем на данные и длиной.
len(myString)читает это поле. Важно:len()возвращает количество байт, а не рун (символов). - Массив (Array): Длина массива является частью его типа и известна на этапе компиляции.
len(myArray)— это, по сути, константа. - Мапа (Map): Внутренняя структура мапы содержит счётчик количества элементов.
len(myMap)возвращает значение этого счётчика. - Канал (Channel):
len(myChan)возвращает количество элементов, находящихся в данный момент в буфере канала.
Связь с CPU-кэшем
Прямой связи между len() и CPU-кэшем нет. Однако, как и любая операция чтения из памяти, её скорость косвенно зависит от кэша.
Если заголовок слайса или мапы уже находится в L1/L2 кэше процессора (например, из-за того, что вы недавно работали с этой переменной), чтение поля длины будет практически мгновенным. Если данные находятся только в оперативной памяти, доступ займёт больше времени. Но даже в худшем случае это чрезвычайно быстрая операция.
Ответ 18+ 🔞
Слушай, а вот этот len() в Go — это вообще не функция, в натуре! Это типа встроенная магия компилятора, которая просто берёт и смотрит в паспорт твоей коллекции. И самое охуенное — это O(1), то есть константа, моментально, на раз-два.
Почему так быстро? Да потому что длина — это неотъемлемая часть любой структуры, она там лежит готовая, как пропуск в хату. len() её не вычисляет, а просто тырит, как последний распиздяй.
- Слайс: У него внутри, в этих его потаённых полях, прямо так и записано: «Привет, я
Len, вот моя цифра».len()просто подглядывает.// Вот что у него внутри, представляешь? type sliceHeader struct { Data uintptr // Куда смотреть Len int // А вот и длина, ебать! Cap int // А это сколько влезет } - Строка: Точно такая же хитрая жопа с указателем и длиной. Только помни:
len()считает байты, а не символы. Хочешь руны — это отдельная история, там ужеutf8.RuneCountInString. - Массив: Да тут вообще смех: длина массива — это часть его типа. Компилятор её знает ещё до того, как ты штаны надел.
len()— это просто подставить готовую циферку. - Мапа: Внутри у неё счётчик элементов тикает.
len()— это глянуть на счётчик. - Канал:
len()покажет, сколько сообщений в буфере лежит и ждёт, пока их кто-нибудь заберёт.
А при чём тут кэш процессора, спросишь? Да ни при чём, напрямую-то. Но если ты только что вовсю дрочил этот слайс, и его заголовок уже в быстром кэше L1 залёг — то чтение длины будет вообще мгновенным, как удар током. Ну а если данные далеко в оперативке — чуть дольше, но всё равно быстрее, чем ты «ёпта» скажешь.
Короче, len() — это супер-пупер быстрая штука. Не парься об этом вообще.