Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
len() для слайса в Go
Функция len() для слайса возвращает текущее количество элементов (длину), содержащихся в слайсе, а не его ёмкость (cap). Это одно из трёх основных свойств слайса (указатель на массив, длина, ёмкость), доступное через встроенные функции Go. len() работает за константное время O(1), так как длина хранится в дескрипторе слайса.
Основные характеристики
- Возвращаемое значение: тип
int, количество доступных элементов "от нулевого до len-1". - Отличие от ёмкости (
cap): длина — это размер логической части слайса, ёмкость — общий размер выделенного в памяти массива. - Работа с nil-слайсом: для
nil-слайсаlen()возвращает 0. - Немодифицируемость:
len()только читает длину, не изменяя слайс.
Примеры использования
Базовый пример
package main
import "fmt"
func main() {
slice := []int{10, 20, 30, 40, 50}
fmt.Printf("Длина слайса: %d\n", len(slice)) // Длина слайса: 5
fmt.Printf("Ёмкость слайса: %d\n", cap(slice)) // Ёмкость слайса: 5
// Обращение к элементам
for i := 0; i < len(slice); i++ {
fmt.Printf("Элемент [%d]: %d\n", i, slice[i])
}
}
Динамическое изменение длины через append()
package main
import "fmt"
func main() {
var slice []int // nil-слайс
fmt.Println("Длина nil-слайса:", len(slice)) // 0
slice = append(slice, 100, 200)
fmt.Println("После append:", slice) // [100 200]
fmt.Println("Длина после append:", len(slice)) // 2
fmt.Println("Ёмкость после append:", cap(slice)) // 2
}
Срезы (slicing) и их длина
package main
import "fmt"
func main() {
original := []string{"a", "b", "c", "d", "e"}
subSlice := original[1:4] // Срез от индекса 1 до 3 (включительно)
fmt.Println("Оригинал:", original, "Длина:", len(original)) // Длина: 5
fmt.Println("Подслайс:", subSlice, "Длина:", len(subSlice)) // Длина: 3
fmt.Println("Ёмкость подслайса:", cap(subSlice)) // Ёмкость: 4
}
Важные нюансы поведения
-
Связь с ёмкостью: длина всегда ≤ ёмкости. При
append()сверх текущей длины может увеличиваться ёмкость. -
len()иmake(): можно создать слайс с начальной длиной и ёмкостью черезmake().slice := make([]int, 5, 10) // Длина: 5, ёмкость: 10 fmt.Println(len(slice)) // 5 fmt.Println(cap(slice)) // 10 -
Итерирование:
len()часто используется для границ в циклах, но в Go предпочитаютrange.// Обычно вместо этого: for i := 0; i < len(slice); i++ { ... } // Используют это (range сам знает длину): for index, value := range slice { ... } -
Безопасность: попытка доступа к элементу с индексом ≥
len()вызовет панику.slice := []int{1, 2, 3} // fmt.Println(slice[5]) // panic: runtime error: index out of range [5] with length 3
Под капотом
Слайс в Go — это структура данных, которая в рантайме представляется как:
type slice struct {
array unsafe.Pointer // Указатель на массив
len int // Текущая длина
cap int // Ёмкость
}
Функция len() просто возвращает поле len этой структуры, что объясняет её константную скорость работы.
Практическое значение
- Алгоритмы и обработка данных:
len()критична для алгоритмов, работающих со срезами. - Проверка на пустоту: вместо сравнения с
nilчасто проверяютlen(slice) == 0. - Буферизация: при работе с буферами (
[]byte) длина указывает на заполненную часть. - Срезы строк: для строк
len()возвращает количество байт, а не рун, что важно для многобайтовых символов UTF-8.
Таким образом, len() — фундаментальная операция для работы со слайсами, предоставляющая эффективный и безопасный способ определения текущего размера динамической коллекции. Понимание разницы между длиной и ёмкостью — ключевой аспект эффективного использования слайсов в Go.