Skip to content

Instantly share code, notes, and snippets.

@mbigras
Last active August 29, 2023 05:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mbigras/a1c96ec65deacb5fa037215849b5c2ba to your computer and use it in GitHub Desktop.
Save mbigras/a1c96ec65deacb5fa037215849b5c2ba to your computer and use it in GitHub Desktop.
This gist contains the cat Unix command—written in Go.

Cat in Go

This gist contains the cat Unix command—written in Go.

The following Go program concatenates files passed as command-line arguments. If you don't pass any command-line arguments, then cat reads from stdin (it's the cat Unix utility).

Getting started

The following procedure shows how to build and run cat.

  1. Navigate to a temporary directory.

    cd $(mktemp -d)
    
  2. Download cat.go Go code.

    wget https://gist.github.com/mbigras/a1c96ec65deacb5fa037215849b5c2ba/raw/90bd1bc0d2db776604395b17baf6d846c1e1433e/cat.go
    
  3. Build cat Go program.

    go build cat.go
    
  4. Pass some input to cat interactively from stdin.

    ./cat
    

    Type something. Press return. Press control-D. Your output should look like the following.

    $ ./cat
    hello world # Manually type "hello world".
    hello world
    
  5. Pass some input through a Unix pipe—also stdin.

    echo hello world | ./cat
    

    Your output should look like the following.

    $ echo hello world | ./cat
    hello world
    
  6. Pass your input through a couple files.

    echo hello > foo.txt
    echo world > bar.txt
    ./cat foo.txt bar.txt
    

    Your output should look like the following.

    $ echo hello >foo.txt
    $ echo world >bar.txt
    $ ./cat foo.txt bar.txt
    hello
    world
    
  7. Pass your input through a couple temporary files.

    ./cat <(echo hello) <(echo world)
    

    Your output should look like the following.

    $ ./cat <(echo hello) <(echo world)
    hello
    world
    
  8. Pass some bad input.

    ./cat idontexist
    

    Your output should look like the following.

    $ ./cat idontexist
    2023/01/02 14:33:45 open idontexist: no such file or directory
    
  9. Clean up.

    Navigate away and the temporary directory will get automatically cleaned up.

// Program cat concatenates files passed as command-line arguments. If you don't pass any command-line arguments, then cat reads from stdin. Note: This implementation comes from dup2 in Go Programming Language by Kernighan and Donovan.
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
files := os.Args[1:]
if len(files) == 0 {
printLines(os.Stdin)
} else {
for _, arg := range files {
f, err := os.Open(arg)
if err != nil {
log.Fatal(err)
}
printLines(f)
f.Close()
}
}
}
func printLines(f *os.File) {
input := bufio.NewScanner(f)
for input.Scan() {
fmt.Println(input.Text())
}
// Note: Ignore potential errors from input.Err() because that's what dup2 does. Todo: Figure out if I should account for EOF or other errors.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment