ProgrammazioneSviluppatore Backend

Descrivi le caratteristiche dell'uso dei puntatori in Go: quando dovrebbero essere utilizzati, come si differenziano dai riferimenti in altri linguaggi e quali sono le trappole comuni associate al loro utilizzo?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

In Go, un puntatore è una variabile che memorizza l'indirizzo di un'altra variabile. A differenza di alcuni linguaggi, in Go non è possibile eseguire l'aritmetica dei puntatori, il che li rende più sicuri. I puntatori in Go vengono spesso utilizzati per:

  • Passare grandi strutture alle funzioni (per evitare copie).
  • Modificare un oggetto da una funzione esterna.
  • Implementare strutture dati complesse (ad esempio, liste, alberi).

In Go non esiste un supporto esplicito per i tipi di riferimento, come in C++, tuttavia gli slices e le maps sono già di natura referenziale e vengono spesso passati per valore.

Esempio di passaggio di puntatore e valore:

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

Domanda trabocchetto.

Possono i puntatori puntare a costanti o letterali in Go?

Risposta corretta: No, in Go non è possibile ottenere l'indirizzo di una costante o di letterali direttamente. L'indirizzo può essere preso solo da una variabile:

x := 5 p := &x // OK p2 := &10 // Errore di compilazione

Questo è spesso confuso con i linguaggi in cui ciò è consentito.

Esempi di errori reali a causa della conoscenza insufficiente delle sottigliezze dell'argomento.


Storia

In un progetto, uno sviluppatore ha cercato di passare un riferimento a un elemento di uno slice, pensando di poter modificare in sicurezza lo slice tramite un puntatore. Ma si è sbagliato: lo slice contiene un puntatore, ma dopo append() l'indirizzo dell'array sottostante cambia, e le modifiche non si riflettono sempre sui dati originali. Questo ha portato a bug difficili da rilevare (i dati venivano "persi").


Storia

In un progetto è stata creata una lista di puntatori a variabili locali in un ciclo, e dopo l'uscita dal ciclo tutti i puntatori puntavano alla stessa variabile (la variabile iterata del ciclo). L'errore è stato notato solo dopo un crash in produzione.


Storia

Uno sviluppatore ha erroneamente pensato che l'assegnazione di un puntatore liberasse l'oggetto precedente dalla memoria, e ha assegnato esplicitamente il puntatore a nil, aspettandosi la GC immediatamente. Nella pratica, in Go il garbage collector decide quando pulire gli oggetti, ignorando l'azzeramento prematuro dei riferimenti. Questo ha portato a perdite di memoria dove si sperava in un rilascio tempestivo della memoria.