Sobes.tech
Junior

¿Cómo funcionan los slices en Go?

sobes.tech AI

Respuesta de la IA

Un slice es una envoltura ligera sobre un array. No almacena datos por sí mismo, sino que hace referencia a un array base.

Estructura del slice:

  • Puntero al array base: Dirección del primer elemento del slice en memoria.
  • Longitud (Length): Número de elementos en el slice.
  • Capacidad (Capacity): Número de elementos en el array base, disponibles desde el puntero del slice.
// Ejemplo de declaración de un slice
var s []int
s = append(s, 1, 2, 3) // Añadir elementos

// Representación interna del slice s (simplificada)
// struct SliceHeader {
//     Data uintptr // Puntero al array base
//     Len int      // Longitud del slice
//     Cap int      // Capacidad del slice
// }
  • Al crear un slice con make([]T, length, capacity) se crea un array base con la capacidad especificada y un slice que hace referencia a él con la longitud indicada.
  • Al usar un segmento en un array u otro slice (por ejemplo, arr[low:high:max]) se crea un nuevo slice que hace referencia a la misma área de memoria del array base, pero con diferentes punteros, longitud y capacidad.
  • La operación append puede provocar una reasignación de memoria. Si la capacidad actual no es suficiente para añadir nuevos elementos, Go crea un nuevo array base más grande, copia los elementos del antiguo y actualiza el puntero del slice al nuevo array. Esto se llama realojamiento. El crecimiento de la capacidad al hacer append es exponencial (se duplica hasta cierto tamaño, luego el crecimiento se desacelera).
  • Los slices se pasan por valor, pero dado que contienen un puntero al array base, las modificaciones a los elementos del slice (a través del índice) serán visibles en todos los slices que hagan referencia al mismo array.
  • Cambiar la longitud del slice mediante un segmento no afecta al array base, pero puede limitar el acceso a parte de los datos del array base.

Tabla: Comparación entre Length y Capacity

Característica Longitud (Length) Capacidad (Capacity)
Definición Número real de elementos en el slice Número máximo de elementos que puede tener el slice sin realojamiento
Acceso Se usa para acceder a los elementos (s[i]) Define cuántos elementos más se pueden añadir con append antes del realojamiento
Obtención len(s) cap(s)
// Ejemplo de trabajo con capacidad y longitud
s := make([]int, 0, 5) // Longitud 0, capacidad 5
fmt.Println(len(s), cap(s)) // 0 5

s = append(s, 1, 2) // Añadir 2 elementos
fmt.Println(len(s), cap(s)) // 2 5

s = append(s, 3, 4, 5, 6) // Añadir otros 4 elementos, se requiere realojamiento
fmt.Println(len(s), cap(s)) // 6 10 (la capacidad aumentó)