Il linguaggio di programmazione Go, noto anche come Golang, è ampiamente utilizzato per la sua semplicità, efficienza e performance. Una delle caratteristiche chiave di Go è il modo in cui gestisce il passaggio di dati alle funzioni: alcuni tipi di dati vengono passati per valore, mentre altri vengono passati per riferimento. In questo articolo, esploreremo i concetti di passaggio per valore e passaggio per riferimento in Go e i tipi di dati associati a ciascuna modalità.
Passaggio per valore
Nel passaggio per valore, viene effettuata una copia dei dati e questa copia viene passata alla funzione. In altre parole, le modifiche apportate alla copia all'interno della funzione non influenzeranno la variabile originale al di fuori della funzione. In Go, i seguenti tipi di dati sono passati per valore:
Tipi di dati semplici
I tipi di dati semplici, come gli interi (int), i float (float64), le stringhe (string) e i booleani (bool), sono passati per valore. Questo significa che quando passi una variabile di uno di questi tipi a una funzione, la funzione riceverà una copia della variabile, non il riferimento alla variabile originale.
package main
import "fmt"
func modificaInt(numero int) {
numero = 42
}
func main() {
x := 10
modificaInt(x)
fmt.Println(x) // Stampa 10, poiché x è passato per valore
}
Array
Gli array in Go vengono passati per valore. Anche se sono più complessi rispetto a int o string, quando passi un array a una funzione, questa riceverà una copia dell'array originale.
package main
import "fmt"
func modificaArray(arr [3]int) {
arr[0] = 42
}
func main() {
a := [3]int{1, 2, 3}
modificaArray(a)
fmt.Println(a) // Stampa [1 2 3], poiché l'array è passato per valore
}
Struct
Le struct in Go vengono passate per valore, proprio come gli array e gli altri tipi di dati complessi. Quando passi una struct a una funzione, questa riceve una copia della struct originale.
package main
import "fmt"
type Persona struct {
Nome string
Email string
}
func modificaStruct(p Persona) {
p.Nome = "Mario"
p.Email = "mario@site.tld"
}
func main() {
personaOriginale := Persona{"Luca", "luca@site.tld"}
modificaStruct(personaOriginale)
fmt.Println(personaOriginale) // Stampa {Luca luca@site.tld}, poiché la struct è passata per valore
}
Passaggio per riferimento
Nel passaggio per riferimento, viene passato un puntatore o una referenza alla variabile originale. Ciò significa che qualsiasi modifica apportata alla variabile all'interno della funzione influenzerà direttamente la variabile originale. In Go, i seguenti tipi di dati sono passati per riferimento:
Slice
Gli slice in Go sono strutture dati flessibili e sono passati per riferimento. Quando passi un slice a una funzione, la funzione riceve un riferimento al slice originale.
package main
import "fmt"
func modificaSlice(slice []int) {
slice[0] = 42
}
func main() {
s := []int{1, 2, 3}
modificaSlice(s)
fmt.Println(s) // Stampa [42 2 3], poiché il slice è passato per riferimento
}
Map
Anche le map in Go sono passate per riferimento. Quando passi una map a una funzione, questa riceve un riferimento alla map originale.
package main
import "fmt"
func modificaMappa(mappa map[string]int) {
mappa["chiave"] = 42
}
func main() {
m := map[string]int{"chiave": 1}
modificaMappa(m)
fmt.Println(m) // Stampa map[chiave:42], poiché la mappa è passata per riferimento
}
Puntatori
Puoi anche passare esplicitamente un puntatore a una variabile in Go, consentendo al chiamante e alla funzione di accedere e modificare la stessa variabile attraverso il puntatore.
package main
import "fmt"
func modificaConPuntatore(p *int) {
*p = 42
}
func main() {
x := 10
modificaConPuntatore(&x)
fmt.Println(x) // Stampa 42, poiché è stato passato un puntatore
}
In conclusione, in Go il passaggio di dati alle funzioni può avvenire per valore o per riferimento, a seconda del tipo di dato. Comprendere la differenza tra passaggio per valore e passaggio per riferimento è essenziale per scrivere codice Go efficace ed evitare comportamenti inaspettati. Utilizzando questa conoscenza, puoi selezionare il tipo di passaggio appropriato per i tuoi dati in base alle tue esigenze di programmazione.