Building Planet-hackNY in Go

Columbia University

20 November 2013

Aditya Mukerjee

Personal Background

uh-oh

At this point, we know we have to rewrite it all

Go is very Python-like

Overview of Go History

Birth

Systems programming

Design goals

Concurrency in Go

Go's Concurrency Model:

Concurrency in Go: Goroutines

So what is a goroutine?

From the docs:
- A goroutine is "a function executing concurrently with other goroutines in the same address space"
- Goroutines are light
- Goroutines are multiplexed onto multiple OS threads
- Goroutines are similar to the & operator in bash/sh

Synchronicity by Example

func Greet(name string) {
    log.Printf("Greetings, %s!", name)
    time.Sleep(3 * time.Second)
}

func main() {
    Greet("Alice")
    Greet("Bob")

    time.Sleep(5 * time.Second)
}

Goroutines by Example

func Greet(name string) {
    log.Printf("Greetings, %s!", name)
    time.Sleep(3 * time.Second)
}

func main() {
    go Greet("Alice")
    go Greet("Bob")

    time.Sleep(5 * time.Second)
}

Yes, it really is just that easy.

Goroutines vs. Callbacks

Concurrency in Go: Channels

Channels by Example:

func Greet(name string, response_chan chan string) {
    greeting := fmt.Sprintf("Greetings, %s!", name)
    response_chan <- greeting
}

func main() {

    cs := make(chan string)
    go Greet("Alice", cs)
    greeting := <-cs
    log.Print(greeting)
}

Let's take a closer look at that:

func Greet(name string, response_chan chan string) {
    time.Sleep(3 * time.Second)
    greeting := fmt.Sprintf("Greetings, %s!", name)
    response_chan <- greeting
    log.Print("Greeting function is tired - sleeping for a bit")
    time.Sleep(3 * time.Second)
    log.Print("now the greeting function is done sleeping - terminating")
}

func main() {

    cs := make(chan string)
    go Greet("Alice", cs)
    log.Print("Continuing execution while we wait for greeter to respond")
    greeting := <-cs
    log.Print(greeting)
    time.Sleep(10 * time.Second)
}

Go makes concurrency easy

Advantages of Go

Disadvantages of Go

Python in 2009

Go in 2013

Speed

Type system

func addOne(a int) int {
    return a + 1
}
func main(){
    a := 5
    b := addOne(a) //Assigned type is inferred
}

Go for Python/Ruby/Node.js programmers

See also: Go for Pythonists
See also: Effective Go

Data processing in Go

Go Standard Library

Some tools included for free in the standard library:

Data scraping in Go

Rate-limiting a Twitter API Client in Go

//throttledQuery executes and automatically throttles queries according to SECONDS_PER_QUERY
func (c TwitterApi) throttledQuery() {
    for q := range c.queryQueue {
        now := time.Now()

        err := c.execQuery(q.url, q.form, q.data, q.method)

        q.response_ch <- struct {
            data interface{}
            err  error
        }{q.data, err}

        time.Sleep(SECONDS_PER_QUERY - time.Since(now))
    }
}

Channels for parallel computation

Selecting Channels

select {
    case <-algorithm1:
        // a read from ch has occurred
    case <-algorithm2:
        // the read from ch has timed out
}
select {
    case <-ch:
        // a read from ch has occurred
    case <-timeout:
        // the read from ch has timed out
}

Example: Data Collection with Background Computation

Getting started with Go

Function declaration

func doSomething(){
    var foo int
    foo = 6
    bar := 8
}

Zero values

For loops/If statements

func PrintAllNames(names []string){
    for _, name := range names {
        if name != "" {
            fmt.Println(name)
        }
    }
}

Error Handling

func FindUser(c mgo.Collection, username string) result, err{
    var result User
    err := c.Find(bson.M{"username", username}).One(&result)
    return result, err
}

func main(){
    err := FindUser("JohnDoe")
    if err != nil{
        //Handle error
        //Log error message, repeat action, etc.
    }
}

Structs

type CheckingAccount struct {
    Balance int
    superSecretId int64
}
type Person struct {
    MainAccount CheckingAccount
}

type Bank struct {
    Accounts []CheckingAccount
    SavingsAccounts []struct{
        Balance int
        InterestRate float64
    }
}

Interfaces in Go

Using Interfaces

type Account interface {
    Deposit(int) error
}

type CheckingAccount struct {
    Balance int 
        superSecretId int64
}

func (destination CheckingAccount) Deposit(amount int) error {
    destination.Balance += amount
    return nil
}

Writing extensions in C

Other useful munging tools

go-json - automatically generate static struct definitions for JSON unmarshalling
mgo - a MongoDB client library for Go
redigo - A Redis client library in Go

so back to planet hackNY

https://github.com/ChimeraCoder/pluto

but what is this "hackNY" stuff all about, anyway?

HackNY

Startups

Speakers

Alexis Ohanian (Reddit)

Chris Dixon (Hunch, a16z)

moot (don't ask)

USV Partners

Zach Sims & Ryan Bubinski (Codecademy)

(Oh, and, there's food too.)

DemoFest

We love hackNY, and so should you!

Thank you

Aditya Mukerjee