Step 5: The Go version
Go's version reads almost like pseudocode: strings.FieldsFunc splits on every non-letter, a map[string]int counts, and sort.Slice sorts a slice of small structs. There are no generics or ownership rules to think about here; the language aims at being easy to read and fast to compile.
ExampleGo
package main
import (
"fmt"
"sort"
"strings"
"unicode"
)
type entry struct {
word string
count int
}
func countWords(text string) []entry {
words := strings.FieldsFunc(strings.ToLower(text), func(r rune) bool {
return !unicode.IsLetter(r)
})
counts := map[string]int{}
for _, w := range words {
counts[w]++
}
list := make([]entry, 0, len(counts))
for w, c := range counts {
list = append(list, entry{w, c})
}
sort.Slice(list, func(i, j int) bool {
if list[i].count != list[j].count {
return list[i].count > list[j].count
}
return list[i].word < list[j].word
})
return list
}
func main() {
text := "The quick brown fox jumps over the lazy dog. The end!"
for _, e := range countWords(text) {
fmt.Printf("%-6s %d\n", e.word, e.count)
}
}Output
the 3 brown 1 dog 1 end 1 fox 1 jumps 1 lazy 1 over 1 quick 1
The map's counts[w]++ works even for a new word because a missing key reads as the zero value 0. All four programs print exactly the same lines.
Quick check
Why does counts[w]++ work for a word seen for the first time in Go?
Finish the quick check (and any code exercise) to complete this lesson, or mark it done yourself.
Tip: use the left and right arrow keys to move between lessons.