ProgramaciónProgramador de Go

¿Qué son las funciones integradas append, len y cap en Go, cómo funcionan a nivel de lenguaje y qué peligros ocultos asociados con los slices están relacionados con su uso?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

En Go, las funciones integradas append, len y cap juegan un papel clave al trabajar con slices.

  • len(slice) devuelve el número de elementos en el slice.
  • cap(slice) devuelve la capacidad del slice: la cantidad máxima de elementos antes de que se asigne nueva memoria.
  • append(slice, elems ...T), al no tener suficiente capacidad, provoca la creación de un nuevo array (y, por lo tanto, un nuevo almacenamiento subyacente), lo que puede cambiar inesperadamente la semántica de la transmisión del slice.

Ejemplo:

arr := []int{1,2,3} arr2 := append(arr, 4) // arr2 puede estar en el mismo o en un nuevo backing array, dependiendo de cap(arr)

Detalles:

  • Si haces append a un slice que fue "cortado" de otro slice (o array original), puede haber un efecto secundario: modificación de los datos originales.
  • Al pasar slices a funciones, len/cap solo actúan sobre la parte "visible".
  • Al hacer append excediendo cap, se crea un nuevo array, el antiguo no se toca.

Pregunta con trampa

¿Qué pasará si "cortas" un slice y agregas un elemento mediante append? ¿Afectará esto al array original?

Respuesta: Si cap lo permite, append escribirá el elemento "al final" del array original, y los cambios serán visibles a través de todos los slices que referencian el mismo array.

Ejemplo:

a := []int{1,2,3,4} b := a[:2] // [1 2], len=2, cap=4 b = append(b, 10) // a cambia: a -> [1, 2, 10, 4]

Ejemplos de errores reales


Historia

En el equipo se añadieron elementos a un slice hijo, y de repente se modificaron los datos en el array padre; esto causó descoordinación en la lógica de negocio y errores muy difíciles de depurar en la distribución de tareas entre los usuarios.


Historia

Al llamar a append nuevamente en un slice grande, se esperaba que el nuevo array siempre fuera asignado nuevamente, pero de hecho, varias partes del sistema continuaron trabajando con el mismo "backing array", provocando condiciones de carrera y corrupción de datos.


Historia

Un desarrollador asignó un slice de tamaño fijo con make, pero cometió un error y cambió los argumentos de lugar: make([]int, cap, len). Como resultado, la lógica orientada a la capacidad, inesperadamente, funcionaba sobre la longitud, lo que provocó pánico al salir fuera de los límites s[0:len].