Funzioni in Go
Le funzioni sono uno dei mattoni fondamentali della programmazione in Go. Ogni programma Go inizia con la funzione main e si sviluppa attraverso la definizione di funzioni che organizzano il codice in blocchi riutilizzabili. In questa guida esploreremo la dichiarazione delle funzioni, i parametri, i valori di ritorno e le funzioni come cittadini di prima classe.
Dichiarazione di una Funzione
In Go, una funzione viene dichiarata con la parola chiave func, seguita dal nome, dai parametri tra parentesi e dal tipo di ritorno.
package main
import "fmt"
func saluta(nome string) {
fmt.Println("Ciao,", nome)
}
func main() {
saluta("Marco")
}
Se la funzione non restituisce nulla, il tipo di ritorno viene semplicemente omesso.
Parametri e Tipo di Ritorno
I parametri vengono dichiarati con il nome seguito dal tipo. Se piu parametri consecutivi hanno lo stesso tipo, il tipo puo essere specificato solo una volta.
func somma(a, b int) int {
return a + b
}
func main() {
risultato := somma(3, 7)
fmt.Println("Somma:", risultato) // Somma: 10
}
In questo esempio, a e b sono entrambi di tipo int, quindi il tipo e dichiarato una sola volta.
Valori di Ritorno Multipli
Una delle caratteristiche piu potenti di Go e la possibilita di restituire piu valori da una funzione. Questo pattern e ampiamente utilizzato, soprattutto per la gestione degli errori.
func dividi(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("divisione per zero")
}
return a / b, nil
}
func main() {
risultato, err := dividi(10, 3)
if err != nil {
fmt.Println("Errore:", err)
return
}
fmt.Printf("Risultato: %.2f\n", risultato)
}
Valori di Ritorno con Nome
I valori di ritorno possono avere un nome. In questo caso, funzionano come variabili locali inizializzate al valore zero del loro tipo. Un return senza argomenti restituisce i valori correnti delle variabili nominate (naked return).
func rettangolo(larghezza, altezza float64) (area, perimetro float64) {
area = larghezza * altezza
perimetro = 2 * (larghezza + altezza)
return // Restituisce area e perimetro
}
func main() {
a, p := rettangolo(5, 3)
fmt.Printf("Area: %.1f, Perimetro: %.1f\n", a, p)
}
I naked return sono consigliati solo per funzioni brevi, poiche in funzioni lunghe possono ridurre la leggibilita.
Funzioni come Cittadini di Prima Classe
In Go, le funzioni sono valori di prima classe: possono essere assegnate a variabili, passate come argomenti e restituite da altre funzioni.
package main
import "fmt"
func main() {
// Assegnare una funzione a una variabile
operazione := func(a, b int) int {
return a + b
}
fmt.Println(operazione(5, 3)) // 8
// Cambiare l'operazione
operazione = func(a, b int) int {
return a * b
}
fmt.Println(operazione(5, 3)) // 15
}
Tipi di Funzione
In Go e possibile definire un tipo basato su una firma di funzione. Questo e utile per creare interfacce funzionali e callback.
package main
import "fmt"
// Definizione di un tipo funzione
type Operazione func(int, int) int
func applica(a, b int, op Operazione) int {
return op(a, b)
}
func main() {
somma := func(a, b int) int { return a + b }
prodotto := func(a, b int) int { return a * b }
fmt.Println("Somma:", applica(10, 5, somma)) // 15
fmt.Println("Prodotto:", applica(10, 5, prodotto)) // 50
}
Il tipo Operazione rappresenta qualsiasi funzione che accetti due int e restituisca un int.
Funzioni con Piu Parametri dello Stesso Tipo
Quando i parametri consecutivi condividono lo stesso tipo, e possibile raggruppare la dichiarazione.
// Tutti e tre i parametri sono di tipo string
func creaNomeCompleto(nome, secondo, cognome string) string {
return nome + " " + secondo + " " + cognome
}
Funzioni Esportate e Non Esportate
In Go, la visibilita di una funzione e determinata dalla lettera iniziale del suo nome. Le funzioni con la lettera maiuscola iniziale sono esportate (pubbliche), quelle con la minuscola sono non esportate (private al pacchetto).
// Funzione esportata, accessibile da altri pacchetti
func Calcola(x int) int {
return elabora(x)
}
// Funzione non esportata, visibile solo nel pacchetto corrente
func elabora(x int) int {
return x * 2
}
Conclusione
Le funzioni in Go sono semplici nella sintassi ma ricche di funzionalita. I valori di ritorno multipli, i ritorni con nome e le funzioni come cittadini di prima classe rendono Go un linguaggio espressivo e pragmatico. La convenzione di visibilita basata sulla capitalizzazione del nome e un elemento distintivo che promuove un design chiaro dei pacchetti.