Saturday, November 12, 2011

Go has turned 2 years!

Indeed on Nov 10 2009 the Go-team at Google made their work public.
Go has come a long way in these 2 years, thanks to the brilliant team and hundreds of contributors from all over the world. Early 2012 Go 1 will be launched as a hallmark to the world announcing that it is ready for mainstream adoption, being stable and supported for years to come. The past year has seen a great number of refinements and additions so that Go is now faster than ever, building upon a complete standard library and surrounded by hundreds of peripheral 3rd party projects
(see http://godashboard.appspot.com/package).
Go has also made its way in the cloud in Google App Engine, where it will soon be equal in possibilities to the Java and Python environments.
Already now the list of business projects using Go is impressive:
http://go-lang.cat-v.org/organizations-using-go
In only 2 years it can present an equal or greater amount of references than Ruby:
(http://www.ruby-lang.org/en/documentation/success-stories/).
Every day on github alone around 10 projects using Go are created or updated (https://github.com/languages/Go/created)
The release of Go1 will also see the publication of an ever growing number of published books on Go and its applications.
See also the GopherTimes (www.gophertimes.com) for  announcements of the steps and milestones in the evolution and adoption of Go.

Sunday, November 6, 2011

An error-handling scheme with closures

Every time when a function returns we should test whether it resulted in an error: this can lead to repetitive and tedious code. Combining the defer/panic/recover mechanism with closures can result in a far more elegant scheme that we will now discuss. However it is only applicable when all functions have the same signature, which is rather restrictive. A good example of its use is in web applications, where all handler functions are of the following type:
                                         func handler1(w http.ResponseWriter, r *http.Request) { … }

Suppose all functions have the signature:     func f(a type1, b type2)
The number of parameters and their types is irrelevant.
We give this type a name:  fType1 = func f(a type1, b type2)
Our scheme uses 2 helper functions:
i)                     check: a function which tests whether an error occurred, and panics if so:

func check(err os.Error) { if err != nil { panic(err) } }


ii)                   errorhandler: this is a wrapper function. It takes a function fn of our type fType1 and returns such a function by calling fn. However it contains the defer/recover mechanism, outlined in § 13.3

func errorHandler(fn fType1) fType1 {
    return func(a type1, b type2) {
        defer func() {
            if e, ok := recover().(os.Error); ok {
log.Printf("run time panic: %v", err)
            }
        }()
        fn(a, b)
    }
}

When an error occurs it is recovered and printed on the log; apart from simply printing the application could also produce a customized output for the user by using the template package (§ 15.6).

The check() function is used in every called function, like this:

func f1(a type1, b type2) {
    …
    f, _, err := // call function/method
    check(err)
    t, err := // call function/method
    check(err)
    _, err2 := // call function/method
    check(err2)
    …
}

The main() or other caller-function should then call the necessary functions wrapped in errorhandler, like this:

func main() {
    errorHandler(f1)
    errorHandler(f2)
    …
}

Using this mechanism all errors are recovered and the error-checking code after a function call is reduced to check(err).In this scheme different error-handlers have to be used for different function types; they could be hidden inside an error-handling package. Alternatively a more general approach could be using a slice of empty interface as parameter and return type.