Back to blogging again. This time in Go!

I’ve always wanted to have more control over my own blog, reducing as much bells and whistles as possible, and focus on just the essence: The posts themselves.

All my friends know that I’ve been enamored with Go nowadays. This blog engine (static-site generator) is another perfect excuse to write even more Go.

For your reading pleasure, I’ll share some of the blog’s interesting parts you may find useful.

Standard library HTTP server

It is no secret that Go standard library, especially net/http, is amazing. but did you know that you can serve static files in just three lines of code?

import "net/http"
http.Handle("/", http.FileServer(http.Dir(".")))
http.ListenAndServe(":3000", nil)

Third party libraries

To start, I am using github.com/codegangsta/cli library to help me build command line application. It provides a few conveniences such as --help generation and options parsing.

Next thing I need is Markdown parser. To parse and convert Markdown to HTML, I use github.com/russross/blackfriday. It sanitizes user-supplied data, fast, supports extensions, and utf-8 friendly.

As part of the blog engine features, I want it to watch my markdown files and auto-generate HTML pages as I save the file. This is a great use case for inotify and Go has a library for it: github.com/go-fsnotify/fsnotify. The library is easy to use and concise, the entire directory watcher code is only 40 lines long.

package dirwatcher

import (
    "github.com/go-fsnotify/fsnotify"
    "log"
)

func WatchDir(path string, callback func(fsnotify.Event)) error {
    watcher, err := fsnotify.NewWatcher()
    if err != nil { return err }
    defer watcher.Close()

    done := make(chan bool)
    go func() {
        for {
            select {
            case event := <-watcher.Events:
                if event.Op&fsnotify.Write == fsnotify.Write {
                    callback(event)
                }
            case err := <-watcher.Errors:
                if err != nil { log.Println("Error: ", err) }
            }
        }
    }()

    err = watcher.Add(path)
    if err != nil { return err }

    <-done
    return nil
}

Summary

Overall, I had a great time building it. The entire code base is only 375 lines of Go. You can check out the whole code base here.

It took about six/seven hours to write and they are mostly CSS editing as I am not a front-end developer.

I had no idea that static-site generator can be this much fun, I am looking foward to writing more blog posts.