ProgramaciónDesarrollador Backend

Describe las características del trabajo con punteros en Go: cuándo deberían usarse, en qué se diferencian de las referencias en otros lenguajes, y qué trampas típicas están asociadas con su uso?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

En Go, un puntero es una variable que almacena la dirección de otra variable. A diferencia de algunos lenguajes, en Go no se puede realizar aritmética de punteros, lo que los hace más seguros. Los punteros en Go se utilizan a menudo para:

  • Pasar estructuras grandes a funciones (para evitar copias).
  • Modificar un objeto desde una función externa.
  • Para implementar estructuras de datos complejas (por ejemplo, listas, árboles).

En Go, no hay soporte explícito para tipos de referencia como en C++, sin embargo, los slices y maps son de naturaleza referencial y a menudo se pasan por valor.

Ejemplo de pasar un puntero y un valor:

package main import "fmt" type User struct { Name string } func changeNameByValue(u User) { u.Name = "Vasya" } func changeNameByPointer(u *User) { u.Name = "Petya" } func main() { user := User{Name: "Ivan"} changeNameByValue(user) fmt.Println(user.Name) // Ivan changeNameByPointer(&user) fmt.Println(user.Name) // Petya }

Pregunta capciosa.

¿Pueden los punteros apuntar a constantes o literales en Go?

Respuesta correcta: No, en Go no se puede obtener la dirección de una constante o de literales directamente. Solo se puede obtener la dirección de una variable:

x := 5 p := &x // OK p2 := &10 // Error de compilación

Esto a menudo se confunde con lenguajes donde esto es permitido.

Ejemplos de errores reales debido al desconocimiento de los matices del tema.


Historia

En un proyecto, un desarrollador intentó pasar una referencia a un elemento de un slice, creyendo que podría modificar el slice de manera segura a través de un puntero. Pero se equivocó: el slice en sí contiene un puntero, pero después de append() la dirección del arreglo subyacente cambia, y los cambios no siempre se reflejaban en los datos originales. Esto llevó a errores difíciles de rastrear (los datos "se perdieron").


Historia

En el proyecto se creó una lista de punteros a variables locales dentro de un bucle, y al salir del bucle, todos los punteros apuntaban a la misma variable (la variable iteradora del bucle). El error fue notado solo después de un fallo en producción.


Historia

Un desarrollador erróneamente asumió que la asignación de un puntero liberaba el objeto anterior de la memoria, y asignó explícitamente el puntero a nil, esperando que el GC actuara de inmediato. En la práctica, en Go, el recolector de basura decide cuándo limpiar los objetos, ignorando la nulificación prematura de referencias. Esto llevó a fugas donde se esperaba la liberación oportuna de memoria.