package main import ( "bufio" "fmt" "os" "strings" "sync" ) /* @Ref: https://livebook.manning.com/book/go-in-practice/chapter-3/65 1. --reac flag is able to do the race detection 2. How to use scanner to split the word in a file 3. sync.Mutex usage */ func main() { wg := sync.WaitGroup{} w := newWords() for _, file := range os.Args[1:] { wg.Add(1) go func(filename string) { tallyWords(filename, w) wg.Done() }(file) } wg.Wait() fmt.Println("Words that appear more than once:") for word, count := range w.found { if count > 1 { fmt.Printf("%s: %d\n", word, count) } } } type words struct { sync.Mutex found map[string]int } func newWords() *words { return &words{found: make(map[string]int)} } func (w *words) add(word string, n int) { w.Lock() defer w.Unlock() count, ok := w.found[word] if !ok { w.found[word] = n return } w.found[word] = count + n } func tallyWords(filename string, dist *words) error { file, err := os.Open(filename) if err != nil { return err } defer file.Close() scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanWords) for scanner.Scan() { word := strings.ToLower(scanner.Text()) dist.add(word, 1) } return scanner.Err() }