the question is simple, for a input [apple, banana, orange, apple, banana, apple], the program will count it as a map: {apple : 3, orange: 1, banana: 2}, then sort this map by it's values, get [(apple, 3), (banana, 2), (orange, 1)]below is my go version, I'm a go newbie, could you please review it and lecture me how to polish the code? I add a python version for referencepackage main//input, a url.log file, like apple\nbanana\norange\napple\nbanana\napple\n//output, a output.txt file, should be apple: 3\nbanana: 2\norange: 1\nimport (    fmt    bufio    os    sort    strings    io)func main() {    m := make(map[string]int)    // read file line by line    filename := url.log    f, err := os.Open(filename)    if err != nil {        fmt.Println(err)        return    }    defer f.Close()    r := bufio.NewReader(f)    for line, err := r.ReadString('\n'); err == nil; {        url := strings.TrimRight(line, \n)        m[url] += 1  // build the map        line, err = r.ReadString('\n')    }    if err != nil {        fmt.Println(err)        return    }    //sort the map by it's value    vs := NewValSorter(m)    vs.Sort()    // output    f_out, _ := os.Create(output.go.txt)     defer f_out.Close()    var line string    for i, k := range vs.Keys {        line = fmt.Sprintf(%s: %d\n, k, vs.Vals[i])        io.WriteString(f_out, line)    }}type ValSorter struct {    Keys []string    Vals []int}func NewValSorter(m map[string]int) *ValSorter {    vs := &ValSorter {        Keys: make([]string, 0, len(m)),        Vals: make([]int, 0, len(m)),    }    for k, v := range m {        vs.Keys = append(vs.Keys, k)        vs.Vals = append(vs.Vals, v)    }    return vs}func (vs *ValSorter) Sort() {    sort.Sort(vs)}func (vs *ValSorter) Len() int {    return len(vs.Vals)}func (vs *ValSorter) Less(i, j int) bool {    return vs.Vals[i] > vs.Vals[j]}func (vs *ValSorter) Swap(i, j int) {    vs.Vals[i], vs.Vals[j] = vs.Vals[j], vs.Vals[i]    vs.Keys[i], vs.Keys[j] = vs.Keys[j], vs.Keys[i]}python version:from collections import Counterdef main():    count = Counter()    with open(url.log, rb) as f:        for line in f:            url = line.rstrip()            count[url] += 1    with open(output.py.txt, wb) as f:        for key, value in count.most_common():            f.write(%s: %d\n %(key, value))if __name__ == __main__:    main()
code review for count then sort problems (go lang)
python;go
In Go, I would write:package mainimport (    bufio    fmt    io    os    sort)type Key stringtype Count inttype Elem struct {    Key    Count}type Elems []*Elemfunc (s Elems) Len() int {    return len(s)}func (s Elems) Swap(i, j int) {    s[i], s[j] = s[j], s[i]}type ByReverseCount struct{ Elems }func (s ByReverseCount) Less(i, j int) bool {    return s.Elems[j].Count < s.Elems[i].Count}func main() {    m := make(map[Key]Count)    fi, err := os.Open(keys.txt)    if err != nil {        fmt.Println(err)        return    }    defer fi.Close()    r := bufio.NewReader(fi)    for {        line, err := r.ReadString('\n')        if err != nil {            if err == io.EOF && len(line) == 0 {                break            }            fmt.Println(err)            return        }        key := line[:len(line)-1]        m[Key(key)] += 1    }    fi.Close()    e := make(Elems, 0, len(m))    for k, c := range m {        e = append(e, &Elem{k, c})    }    sort.Sort(ByReverseCount{e})    fo, err := os.Create(counts.txt)    if err != nil {        fmt.Println(err)        return    }    defer fo.Close()    for _, e := range e {        line := fmt.Sprintf(%s: %d\n, e.Key, e.Count)        fo.WriteString(line)    }}Input (keys.txt):applebananaorangeapplebananaappleOutput (counts.txt):apple: 3banana: 2orange: 1