Source File: go-coreutils/od/main.go

package main

import (
  "fmt"
  "os"
  "flag"
  "log"
  "bufio"
)

type Opts struct {
  Width int
  Filenames []string
  Hex bool
  Octal bool
  Format string
}

func ParseOpts() (Opts) {
  var opts Opts

  flag.IntVar(&opts.Width, "w", 16, "Width of output grid")
  flag.BoolVar(&opts.Hex, "x", false, "Output hex bytes")
  flag.BoolVar(&opts.Octal, "o", false, "Output octal bytes")

  flag.Parse()

  if flag.NArg() == 0 {
    log.Fatal("USAGE: od [files]")
  }

  if opts.Hex {
    opts.Format = "%0.2x "
  } else {
    opts.Format = "%0.3o "
  }

  opts.Filenames = flag.Args()
  return opts
}

func main() {
  opts := ParseOpts()

  for _, filename := range opts.Filenames {
    reader, err := os.Open(filename)
    defer reader.Close()
    if err != nil { log.Fatalf("can't open: %s: %v", filename, err) }

    buf := bufio.NewReader(reader)
    count := buf.Size()

    fmt.Printf("%0.8o ", 0);

    for index := 0; index < count; index++ {
      data, err := buf.ReadByte()
      if err != nil { break }
      fmt.Printf(opts.Format, data);

      if (index + 1) % opts.Width == 0 {
        fmt.Print("\n")
        fmt.Printf("%0.8o ", index);
      }
    }
  }
}