More Go

November 23, 2009

programming

Still learning and playing with Go, I’ve rewritten my cat experiment, to use a *bufio.Reader, which is more correct I think. I’m also slowly wrapping my mind around the concept of Interfaces. As a non-OO programmer (C and non-OO Perl) is starting to see why this is useful.

So today’s exercises:

  1. Write a cat implementation in Go. See below.
  2. Write a grep implementation in Go. See below.

Cat in go

package main

// A implementation of cat in Go

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

var numberFlag = flag.Bool("n", false, "number each line")

func cat(r *bufio.Reader) bool {
    i := 1;
    for {
        buf, e := r.ReadBytes('\n');
        if e == os.EOF {
            break
        }
        if *numberFlag {
            fmt.Fprintf(os.Stdout, "%5d  %s", i, buf);
            i++
        } else {
            fmt.Fprintf(os.Stdout, "%s", buf)
        }
    }
    return true;
}

func main() {
    flag.Parse();
    if flag.NArg() == 0 {
        cat(bufio.NewReader(os.Stdin))
    }
    for i := 0; i < flag.NArg(); i++ {
        f, e := os.Open(flag.Arg(i), os.O_RDONLY, 0);
        if e != nil {
            fmt.Fprintf(os.Stderr, "%s: error reading from %s: %s\n",
                os.Args[0], flag.Arg(i), e.String());
            continue;
        }
        if !cat(bufio.NewReader(f)) {
            os.Exit(1)
        }
    }
}

Grep in go

package main

// A implementation of Unix grep in Go
// TODO(mg) better error handling

import (
    "os";
    "fmt";
    "bufio";
    "regexp";
    "flag";
)

var numberFlag = flag.Bool("n", false, "number each line")
var filenameFlag = flag.Bool("l", false, "print names of matching files")

func grep(r *bufio.Reader, reg string) (match bool) {
    i := 0;
    for {
        buf, e := r.ReadBytes('\n');
        i++;
        if e == os.EOF {
            break
        }
        if m, _ := regexp.Match(reg, buf); m == true {
            match = true;
            if *filenameFlag {
                return match
            }
            if *numberFlag {
                fmt.Fprintf(os.Stdout, "%5.d:  %s", i, buf)
            } else {
                fmt.Fprintf(os.Stdout, "%s", buf)
            }
        }
    }
    return match;
}

func main() {
    flag.Parse();
    if flag.NArg() < 1 {
        fmt.Fprintf(os.Stderr, "%s: missing regexp\n", os.Args[0]);
        os.Exit(1);
    }
    if flag.NArg() == 1 {
        if grep(bufio.NewReader(os.Stdin), flag.Arg(0)) {
            if *filenameFlag {
                fmt.Fprintf(os.Stdout, "(standard input)\n");
            }
        }
    }
    for i := 1; i < flag.NArg(); i++ {
        f, e := os.Open(flag.Arg(i), os.O_RDONLY, 0);
        if e != nil {
            fmt.Fprintf(os.Stderr, "%s: error reading from %s: %s\n",
                os.Args[0], flag.Arg(i), e.String());
            continue;
        }
        if grep(bufio.NewReader(f), flag.Arg(0)) {
            if *filenameFlag {
                fmt.Fprintf(os.Stdout, "%s\n", flag.Arg(i))
            }
        }
    }
}
Misc