← Назад к вопросам

Что такое len у слайса?

1.3 Junior🔥 91 комментариев
#Основы Go

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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
}

Важные нюансы поведения

  1. Связь с ёмкостью: длина всегда ≤ ёмкости. При append() сверх текущей длины может увеличиваться ёмкость.

  2. len() и make(): можно создать слайс с начальной длиной и ёмкостью через make().

    slice := make([]int, 5, 10) // Длина: 5, ёмкость: 10
    fmt.Println(len(slice)) // 5
    fmt.Println(cap(slice)) // 10
    
  3. Итерирование: len() часто используется для границ в циклах, но в Go предпочитают range.

    // Обычно вместо этого:
    for i := 0; i < len(slice); i++ { ... }
    
    // Используют это (range сам знает длину):
    for index, value := range slice { ... }
    
  4. Безопасность: попытка доступа к элементу с индексом ≥ 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.

Что такое len у слайса? | PrepBro