.. highlight:: go catn.go ======= :: // catn.go /* In the following code, panic us used instead of os.Exit to quit the program. Calling panic ensures deferred functions are called. Calling os.Exit skips calling deferred functions. See https://groups.google.com/forum/#!topic/golang-nuts/_Twwb5ULStM for discussion of how to get both error codes and deferred functions to work correctly. */ package main import ( "bufio" "fmt" "os" "strings" ) // Split a file name string like "conf.py" into strings "conf" and "py". func splitAtLastDot(name string) (string, string) { dotLoc := strings.LastIndex(name, ".") if dotLoc == -1 { return name, "" } return name[:dotLoc], name[dotLoc+1:] } func main() { // // check number of command-line arguments // nargs := len(os.Args) // os.Args contains command-line arguments if nargs != 2 { fmt.Println("Error: exactly one filename argument must be provided") panic("exited") } inname := os.Args[1] // // open the input file // infile, err := os.Open(inname) defer infile.Close() // run this when the function is done if err != nil { fmt.Printf("Error: cannot open file \"%s\" (%s)", inname, err) panic("exited") } // // open the output file // n, ext := splitAtLastDot(inname) outname := n + "-lines." + ext outfile, err := os.Create(outname) // deletes existing file with same name defer outfile.Close() // run this when the function is done if err != nil { fmt.Printf("Error: cannot create file \"%s\" (%s)", outname, err) panic("exited") } // // create the writer // writer := bufio.NewWriter(outfile) defer writer.Flush() // run this when the function is done // // process the files line by line with a scanner // scanner := bufio.NewScanner(infile) num := 1 for scanner.Scan() { line := scanner.Text() // fmt.Printf("%5d %s\n", num, line) // uncomment to print to screen fmt.Fprintf(writer, "%5d %s\n", num, line) num++ } fmt.Println("Results written to " + outname + ".") }