Go, Networked (January 21, 2010)

# The Go Programming Language

## Russ Cox

### CNS Winter Research Review
January 21, 2010

# Go

## New

## Experimental

## Concurrent

## Garbage-collected

## Systems

## Language

# Hello, world

    package main

    import "fmt"

    func main() {
    	fmt.Printf("Hello, 世界\n")
    }

# History

## Design started in late 2007.

## Implementation starting to work mid-2008.

## Released as an open source project in November 2009.

## Work continues.

##

## Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others

# Goals and Motivation

## Go fast!

## Make programming fun again.

## Targeted at systems software, broadly.

# Why isn't programming fun?

## Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:

- verbose, lots of repetition
- too much focus on type hierarchy
- types get in the way as much as they help
- compiles take far too long

## Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:

- errors at run time that should be caught statically
- no compilation means slow code

## Can we combine the best of both?

# Why a new language?

## No new systems language in 10+ years.

## Current languages designed before ...

### ... rise of large-scale, networked and multicore computing

### ... rise of Internet-scale distributed development (many libraries)

# Go

## Make the language fast.

## Make the tools fast.

# Compilation Demo

## Build all standard Go packages: ~120,000 lines of code.

# Go in one slide

## Lightweight syntax.

## Static types: enough to compile well, but inferred much of the time.

## Methods: on any type, orthogonal to type system.

## Abstract types: interface values, relations inferred statically.

## Visibility: inferred from case of name.

## First-class functions.

## Garbage collection.

## Lightweight feel of a scripting language but compiled.

# Go, concurrently

## Cheap to create a new flow of control (goroutine):

    func main() {
    	go expensiveComputation(x, y, z)
    	anotherExpensiveComputation(a, b, c)
    }

## Two expensive computations in parallel.

# Go, concurrently

## Cheap to create a new flow of control (goroutine):

    	for {
    		rw := l.Accept()
    		conn := newConn(rw, handler)
    		go conn.serve()
    	}

## Concurrent web server.

## Network connections multiplexed onto epoll.

- many blocked Read calls != many blocked OS threads

# Go, synchronized

## Use explicit messages to communicate and synchronize.

    func computeAndSend(ch chan int, x, y, z int) {
    	ch <- expensiveComputation(x, y, z)
    }

    func main() {
    	ch := make(chan int)
    	go computeAndSend(ch, x, y, z)
    	v2 := anotherExpensiveComputation(a, b, c)
    	v1 := <-ch
    	fmt.Println(v1, v2)
    }

## Notice communication of result in addition to synchronization.

# Go, synchronized

## RPC client

    func (client *Client) Call(method string, args, reply interface{}) os.Error {
        // Send RPC message.
        call := client.Go(method, args, reply, nil)

        // Read reply from Done channel.
        <-call.Done

        return call.Error
    }

# Go, synchronized

## RPC client demux

    func (client *Client) input() {
    	for {
    		resp := client.readResponse()
    		client.mutex.Lock()
    		c := client.pending[resp.Seq]
    		client.pending[resp.Seq] = c, false
    		client.mutex.Unlock()
    		if resp.Error != "" {
    			c.Error = os.ErrorString(resp.error)
    		}
    		resp.Decode(c.Reply)
    		c.Done <- c
    	}
    }

# Go, synchronized

## RPC client demux

    func (client *Client) input() {
    	for {
    		resp := client.readResponse()
    		client.mutex.Lock()
    		c := client.pending[resp.Seq]
    		client.pending[resp.Seq] = c, false
    		client.mutex.Unlock()
    		if resp.Error != "" {
    			c.Error = os.ErrorString(resp.error)
    		}
    		resp.Decode(c.Reply)
    		c.Done <- c
    	}
    }

## Read response from network.

# Go, synchronized

## RPC client demux

    func (client *Client) input() {
    	for {
    		resp := client.readResponse()
    		client.mutex.Lock()
    		c := client.pending[resp.Seq]
    		client.pending[resp.Seq] = c, false
    		client.mutex.Unlock()
    		if resp.Error != "" {
    			c.Error = os.ErrorString(resp.error)
    		}
    		resp.Decode(c.Reply)
    		c.Done <- c
    	}
    }

## Look up request by sequence number.

# Go, synchronized

## RPC client demux

    func (client *Client) input() {
    	for {
    		resp := client.readResponse()
    		client.mutex.Lock()
    		c := client.pending[resp.Seq]
    		client.pending[resp.Seq] = c, false
    		client.mutex.Unlock()
    		if resp.Error != "" {
    			c.Error = os.ErrorString(resp.error)
    		}
    		resp.Decode(c.Reply)
    		c.Done <- c
    	}
    }

## Decode response fields from payload.

# Go, synchronized

## RPC client demux

    func (client *Client) input() {
    	for {
    		resp := client.readResponse()
    		client.mutex.Lock()
    		c := client.pending[resp.Seq]
    		client.pending[resp.Seq] = c, false
    		client.mutex.Unlock()
    		if resp.Error != "" {
    			c.Error = os.ErrorString(resp.error)
    		}
    		resp.Decode(c.Reply)
    		c.Done <- c
    	}
    }

## Tell client that it finished.

# Go, synchronized

## RPC client demux

    func (client *Client) input() {
    	for {
    		resp := client.readResponse()
    		client.mutex.Lock()
    		c := client.pending[resp.Seq]
    		client.pending[resp.Seq] = c, false
    		client.mutex.Unlock()
    		if resp.Error != "" {
    			c.Error = os.ErrorString(resp.error)
    		}
    		resp.Decode(c.Reply)
    		c.Done <- c
    	}
    }

## Can create multiple Calls with same Done channel and distinguish which finished by inspecting value sent on channel.

# Goroutine demo

## Chain together 100,000 goroutines connected by 100,001 channels.

## Send a value to one end of the chain.

## Each passes it along, increments.

## Receive value out the other end of the chain.

# Go Status

## Open source:

- released on November 10, 2009
- regular releases (~ weekly)
- all development done in public Mercurial repository
- outside contributions welcome
- two independent compiler implementations
- XML, JSON, HTTP, TLS/SSL, native RPC, (network channels,) ...

# Go Status

## Open source

## Portable:

- FreeBSD, Linux, OS X (x86, x86-64)
- (in progress) Linux arm, Native Client x86, Windows x86.

# Go Status

## Open source

## Portable

## Still in progress, experimental. Yet to come:

- production garbage collector
- generics?
- exceptions?
- unions or sum types?

# Questions?