Friday, November 20, 2009

Parsing a JSON document and applying it to an HTML template in Google Go

Here's some simple code to parse a JSON document and the transform it into an HTML document using the Google Go packages json and template.

If you've done anything in a scripting language then you'll probably be surprised by the generation of fixed struct types that have to match the parsed JSON document (or at least match some subset of it). Also because of the way reflection works in Google Go the struct member names need to be in uppercase (and for that reason I've used uppercase everywhere).

import (
"fmt";
"os";
"json";
"template"
)

type Row struct {
Column1 string;
Column2 string;
}

type Document struct {
Title string;
Rows []Row;
}

const a_document = `
{
"Title" : "This is the title",
"Rows" : [ { "Column1" : "A1", "Column2" : "B1" },
{ "Column1" : "A2", "Column2" : "B2" }
]
}`

const a_template = `
<html>
<head><title>{Title}</title></head>
<body>
<table>
{.repeated section Rows}
<tr><td>{Column1}</td><td>{Column2}</td></tr>
{.end}
</body>
</html>`

func main() {

// The following code reads the JSON document in
// a_document and turns it into the Document structure
// stored in d

var d Document;
ok, e := json.Unmarshal( a_document, &d );

if ok {

// This code parses the template in a_template places
// it in t then it applies the parsed JSON document in
// d to the template and prints it out

t, e := template.Parse( a_template, nil );
if e == nil {
t.Execute( d, os.Stdout );
} else {
fmt.Printf( e.String() );
}
} else {
fmt.Printf( e );
}
}

All the real work is done my main() by calling json.Unmarshal, template.Parse and then Execute.

Here's the Makefile and output:

$ cat Makefile
P := template
all: $P

$P: $P.6
6l -o [email protected] $^

%.6: %.go
6g $<
$ make
6g template.go
6l -o template template.6
$./template

<html>
<head><title>This is the title</title></head>
<body>
<table>
<tr><td>A1</td><td>B1</td></tr>
<tr><td>A2</td><td>B2</td></tr>
</body>
</html>

Labels:

Thursday, November 19, 2009

Installing Google Go on Mac OS X

I decided to have a go with Google Go since I'm an old fogey C/C++ programmer. Any new innovation in the C/C++ family gets me excited and Google Go has quite a few nice features (garbage collection is really nice to have and channels make me think of all the work I did in CSP).

I decided to go with the 6g compiler since gccgo doesn't have garbage collection implemented yet and hence there's no way to free memory. The only way to get 6g is to mirror its Mercurial repository. So...

Step 1: Install Mercurial

For that I used prebuilt packages from here and got Mercurial 1.4 for Mac OS X 1.5 (no, I haven't upgraded to Snow Leopard yet).

Step 2. Set GOROOT

I just did a quick cd ; mkdir go ; export GOROOT=$HOME/go to get me started.

Step 3. Clone the 6g repository

That was a quick hg clone -r https://go.googlecode.com/hg/ $GOROOT followed by the hard part: compiling it. You need to have gcc, make, bison and ed installed (whcih I do since I do development work on my Mac).

Step 5. Set GOBIN

This points to where the binaries will go, for me that's $HOME/bin since I'll be doing local development using Go. And I updated PATH to include $GOBIN.

Step 4. Compile 6g

You first need to set GOARCH and GOOS. For me that's amd64 for the architecture (the Intel Core 2 Duo in my Macbook Air is a 64-bit processor) and darwin for the OS (since this is a Mac).

$ export GOARCH=amd64
$ export GOOS=darwin

Then you can actually do the compile:

$ cd $GOROOT/src
$ ./all.bash

This does a build and test of 6g and it was very fast to build (although I'm used to building gcc which is a bit of a monster).

Step 5. Write a Hello, World! program

Here's my first little Google Go program (filename: hw.go) just to test the 6g compiler.

package main

import "fmt"

func main() {
fmt.Printf( "Hello, World\n" );
}

To simplify building I made a minimal Makefile:

all: hw
hw: hw.6 ; 6l -o [email protected] $^
%.6: %.go ; 6g $<

And then the magic moment:

$ make
6g hw.go
6l -o hw hw.6
$ ./hw
Hello, World!

And now for a real project... get SQLite to interface to it.

Labels: ,