Funzioni per Collezioni
Le collezioni in Go sono essenzialmente mappe, slice e array (e gli array sono poco usati).
Una collezione è di qualcosa. Go non ha un meccanismo nativo per parametrizzare tale qualcosa, cioè non ha generics come Java.
Qualsiasi funzione operi su una collezione deve essere esplicitamente definita per ogni caso specifico di collezione.
Non esistono definizioni parametriche, come in Java o C++.
(430collection-functions.go):
// Go non supporta 'generics' come Java o C++
// Le funzioni che operano su collezioni devono
// essere scritte quando servono
package main
import "strings"
import "fmt"
// Ritorna il primo indice della stringa t
// o -1 se non trovata
func Index(vs []string, t string) int {
// i è l'indice, v una stringa della slice
for i, v := range vs {
if v == t {
return i
}
}
return -1
}
// Ritorna true se la stringa t è nella slice
func Include(vs []string, t string) bool {
return Index(vs, t) >= 0
}
// Ritorna true se una delle stringhe nella slice
// soddisfa il predicato f
// Il predicato è una funzione di filtro che deve
// essere fornita come parametro attuale
func Any(vs []string, f func(string) bool) bool {
for _, v := range vs {
if f(v) {
return true
}
}
return false
}
// Ritorna true se tutte le stringhe nella slice
// soddisfano il predicato f
func All(vs []string, f func(string) bool) bool {
for _, v := range vs {
if !f(v) {
return false
}
}
return true
}
// Ritorna una nuova slice contenente tutte le stringhe
// che soddisfano il predicato f
func Filter(vs []string, f func(string) bool) []string {
vsf := make([]string, 0)
for _, v := range vs {
if f(v) {
vsf = append(vsf, v)
}
}
return vsf
}
// Ritorna una nuova slice contenente i risultati
// dell'applicare la funzione f ad ogni stringa della
// slice originale
func Map(vs []string, f func(string) string) []string {
vsm := make([]string, len(vs))
for i, v := range vs {
vsm[i] = f(v)
}
return vsm
}
func main() {
// Prova delle varie funzioni su collezioni
var strs = []string{"peach", "apple", "pear", "plum"}
fmt.Println(Index(strs, "pear"))
fmt.Println(Include(strs, "grape"))
// HasPrefix - libreria
fmt.Println(Any(strs, func(v string) bool {
return strings.HasPrefix(v, "p")
}))
fmt.Println(All(strs, func(v string) bool {
return strings.HasPrefix(v, "p")
}))
// Contains - libreria
fmt.Println(Filter(strs, func(v string) bool {
return strings.Contains(v, "e")
}))
// Sono state usate funzioni anonime, ma si possono
// anche usare funzioni col nome del tipo corretto
// ToUpper converte a maiuscole - libreria
fmt.Println(Map(strs, strings.ToUpper))
}
Una segnatura molto comune delle funzioni di gestione collezioni ha come lista parametri:
- la collezione da trattare passata per riferimento
- una funzione di trattamento da applicare alla collezione
e ritorna un valore di qualche tipo.
Se la funzione di trattamento ritorna un booleano, viene detta funzione predicato.