UPDATE: This project is now available to clone on Gitorious: https://gitorious.org/freq-go/

I'm tinkering with the new Google "Go" language, as I have a need to know a modern, compiled language, and can't really bring myself to learn "C" - particularly as I always said I never would! As an exercise, I decided to re-code freq.py in Go, to see what the experience was like - here is the result. This probably requires Google Go version 1.x (I'm using 1.0.2).

You can compile it to a stand-alone executable with:

go build freq.go

This will create an executable file called "freq" in the current directory. To run it, do:

command | ./freq

Where command is any Linux command that produces text output on stdout, for example "grep" or "cat".

To just run it without building a stand-alone executable, do:

command | go run freq.py

Again, command is any Linux command that produces text on stdout.

As with the python version, the following test data produces the same results:

Test data (in a file called testdata.txt):

red
green
blue
green
blue
red
green
blue
green
blue
green
blue
green
blue
blue
blue
blue

This produces the following results when run through freq.go with this command:

cat testdata.txt | ./freq
2 11.76% red
6 35.29% green
9 52.94% blue
Total 17 items

Here's the go source code:

 


// Generate frequency report of strings read on stdin
package main

import ("fmt"
	"os"
	"io"
	"bufio"
	"strings"
	"sort"
)


type sample struct{
	count	int64
	item	string
}

type FreqTable []sample

func (s FreqTable) Len() int {
	return len(s)
}

func (s FreqTable) Less(i,j int) bool {
	return s[i].count < s[j].count
}

func (s FreqTable) Swap(i,j int) {
	s[i], s[j] = s[j],s[i]
}

func min( i, j int ) int {
	if i < j { return i }
	return j
}

func main() {
	stdin_buf := bufio.NewReader( os.Stdin )
	data := make(map[string]int64, 1000)
	line_count := 0
	for {
		line_in, isPref, err := stdin_buf.ReadLine()
		if err == io.EOF { break }
		if err != nil {
			fmt.Println( err )
			return
		}
		if isPref {
			fmt.Println( "Error: input line too long." )
			return
		}
		str := strings.TrimSpace( string( line_in ) )
		if string( str ) != "" {
			data[ str ] ++
			line_count ++
		}
	}
	freq := make(FreqTable, 0 )
	tmp := sample{ 0, "" }
	one_pc := 100.0/float64(line_count)
	for str, count := range data {
		tmp.count = count
		tmp.item = str
		freq = append( freq, tmp )
	}
	sort.Sort( freq )
	for _, samp := range freq[:] {
		fmt.Printf("%d %3.2f%% %sn", samp.count, float64(samp.count) * one_pc, samp.item)
	}
	fmt.Printf("Total %d itemsn",line_count)
}