beginner – Plan 9 freq(1) in go

I implemented the freq(1) program from Plan 9 in go.

/* print histogram of character frequencies */
package main

import (
    "bufio"
    "flag"
    "fmt"
    "io"
    "log"
    "os"
    "sort"
    "unicode"
)

var dflag = flag.Bool("d", false, "print decimal value")
var xflag = flag.Bool("x", false, "print hex value")
var oflag = flag.Bool("o", false, "print octal value")
var cflag = flag.Bool("c", false, "print unicode character if printable")
var rflag = flag.Bool("r", false, "count UTF8 sequences (runes)")

func main() {
    var freq func(*os.File, map(int32)int) = freqBytes
    counts := make(map(int32)int)
    var codes ()int32

    flag.Parse()
    if (!*dflag && !*oflag && !*xflag && !*cflag) {
        *dflag = true
        *oflag = true
        *xflag = true
        *cflag = true
    }
    if (*rflag) {
        freq = freqRunes
    }
    if (len(flag.Args()) == 0) {
        freq(os.Stdin, counts)
    } else {
        for _, arg := range flag.Args() {
            if arg == "-" {
                freq(os.Stdin, counts)
            } else {
                f, err := os.Open(arg)
                if err != nil {
                    log.Fatal(err)
                }
                freq(f, counts)
                f.Close()
            }
        }
    }
    for code := range counts {
        codes = append(codes, code)
    }
    sort.Slice(codes, func(i, j int) bool { return codes(i) < codes(j) })
    for _, code := range codes {
        if (*dflag) {
            fmt.Printf("%3d ", code)
        }
        if (*oflag) {
            fmt.Printf("%03o ", code)
        }
        if (*xflag) {
            fmt.Printf("%02x ", code)
        }
        if (*cflag) {
            c := rune(code)
            if (!unicode.IsPrint(c) || unicode.IsSpace(c)) {
                c = '-'
            }
            fmt.Printf("%c ", c)
        }
        fmt.Printf("%8dn", counts(code))
    }
}

func freqRunes(f *os.File, counts map(int32)int) {
    in := bufio.NewReader(f)

    for {
        r, n, err := in.ReadRune()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatal(err)
        }
        if r == unicode.ReplacementChar && n == 1 {
            continue
        }
        counts(r)++
    }
}

func freqBytes(f *os.File, counts map(int32)int) {
    in := bufio.NewReader(f)

    for {
        b, err := in.ReadByte()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatal(err)
        }
        counts(int32(b))++
    }
}

freq(1) counts the occurrences of each byte (or each rune, if the -r option is given) in the standard input or the given files. More information on the manual. Unprintable and space characters are replaced with a -. Here is an example of usage with an Esperanto Lorem Ipsum:

 $ echo "eĥoŝanĝo ĉiuĵaŭde" | ./freq -r
 10 012 0a -        1
 32 040 20 -        1
 97 141 61 a        2
100 144 64 d        1
101 145 65 e        2
105 151 69 i        1
110 156 6e n        1
111 157 6f o        2
117 165 75 u        1
265 411 109 ĉ        1
285 435 11d ĝ        1
293 445 125 ĥ        1
309 465 135 ĵ        1
349 535 15d ŝ        1
365 555 16d ŭ        1

Each line prints the codepoint (in decimal, octal and hex) of the rune and the rune itself followed by the occurrence count.

How can I make the code more elegant and idiomatic?