Per definire una funzione Go mette a disposizione la parola chiave func seguita dal nome della funzione, l’elenco dei tipi attesi e l’elenco dei tipi restituiti, questo perchè in Go le funzioni possono restituire più valori in modo sequenziale,
1 2 3 |
func duplica(valore string) string { return valore + valore } |
Nel caso sopra ho definito la funzione duplica che riceve in ingresso una stringa e restituisce la string concatenata con se stessa
E’ possibile definire più parametri in ingresso e se i parametri sono dello stesso tipo Go permette di dichiarare il tipo una volta sola
1 2 3 4 5 6 7 |
func concatena(primo string, secondo string) string { return primo + secondo } func concatena2(primo, secondo string) string { return primo + secondo } |
In questo caso la funzione concatena riceve 2 stringhe in ingresso e le concatena dando il valore in uscita. Essendo parametri dello stesso tipo è possibile dichiarare il tipo una volta sola.
Anche in uscita è possibile definire più parametri
1 2 3 4 5 6 7 8 9 10 |
func conta(primo, secondo string) (int, int) { var a = len(primo) var b = len(secondo) return a, b } func main() { fmt.Println(conta("primo", "secondo")) var _, b = conta("primo", "secondo") fmt.Println(b) } |
In questo la funzione restituisce la lunghezza delle 2 stringhe ricevute in ingresso. E’ possibile anche ignorare una delle 2 variabili tramite la parola chiave _.
Go mette anche a disposizione un meccanismo per definire un numero infinito di parametri in ingresso tramite la parola chiave …
1 2 3 4 5 |
func conta2(parole ...string) { for _, parola := range parole { fmt.Print(fmt.Sprintf("%d ", len(parola))) } } |
In questo caso ho definito una lista di valori in ingresso e per ognuno di essi restituisco la lunghezza della parola
Go permette di ritornare la funzione come tipo di ritorno di una funzione e di assegnarla ad una funzione e di poterlo assegnare ad una variabile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
func conta3() func(...string) { var counter int = 1 return func(parole ...string) { fmt.Print("esecuzione ", counter, " ") counter++ for _, parola := range parole { fmt.Print(fmt.Sprintf("%d ", len(parola))) } fmt.Println() } } func main() { contatore := conta3() contatore("primo", "secondo", "terzo") contatore("terzo", "quarto", "quinto") contatore2 := func(parole ...string) { for _, parola := range parole { fmt.Print(fmt.Sprintf("%d ", len(parola))) } fmt.Println() } contatore2("primo", "secondo", "terzo") contatore2("terzo", "quarto", "quinto") } |
Nell’esempio ho definito una funzione conta3 che riceve una lista di valori variabili in ingresso e che per ognuno di essi elabora la lunghezza e la stampa. Successivamente assegno la funzione ad una variabile e la eseguo invocando la variabile stessa con i parametri in ingresso. Posso ottenere un comportamento analogo definendo la function direttamente dopo il nome della variabile ma in questo caso perdo la gestione della variabile di stato counter.
Infine Go supporta la ricorsione ovvero una funzione che elabora il risultato richiamando se stesso e basando il tutto su una condizione di uscita. Classico esempio è la funzione fattoriale
1 2 3 4 5 6 7 |
func fattoriale(valore int) int { if valore == 0 { return 1 } else { return valore * fattoriale(valore-1) } } |