Go for Python Hackers

Greg Ward <greg@gerg.ca>
@gergdotca
PyCon Canada 2013
Toronto, ON • Aug 11, 2013

Go in a nutshell

Useful links

Basic type system

var a int = 17
var b int32 = 15
c := a + 15           // ✓
d := a + b            // ✕ (mismatched types int and int32)

Builtin types (1)

Builtin types (2)

Object-oriented (sort of!)

three key ideas:
  1. attach methods to any user-defined type
  2. composition, not inheritance
  3. interfaces

Methods (1)

type User struct {
	uid uint32
	firstName string
	lastName string
}

func (u User) FullName() string {
	return u.firstName + " " + u.lastName
}
(syntax probably unfamiliar, but the idea is old hat)

Methods (2)

type Uid uint32

func (uid Uid) Next() Uid {
	return uid + 1
}
(OK, that's pretty cool)

Composition (hard way)

type User2 struct {
	uid Uid
	privs PrivilegeSet
}

func (u User2) HasPrivilege(name string) bool {
	return u.privs.HasPrivilege(name)
}

func (u User2) SetPrivilege(name string) {
	u.privs.SetPrivilege(name)
}

func main() {
	var user2 User2
	user2.SetPrivilege("login")
}

Easy way: embedding!

type User3 struct {
	uid Uid
	PrivilegeSet   // anonymous member
}                      // (makes it embedded)

func main() {
	// User3 has the same API as User2
	var user3 User3
	user3.SetPrivilege("login")
}

Interfaces

type PrivilegeSet interface {
	HasPrivilege(name string) bool
	SetPrivilege(name string)
}

Control flow

Error handling

classic example: what if we write some data to a file, but then get an error?
func (file *File) Write(b []byte) (n int, err error)
rationale: (this is easily Go's most controversial design decision)

Concurrency (1)

func main() {
	// launch a background goroutine, send an
	// endless stream of requests to it, and
	// print each responses
	data := make(chan string)
	go responder(data)
	for {
		data <- "ping"
		response := <-data
		fmt.Printf("<- %s\n", response)
	}
}

Concurrency (2)

// receive a stream of requests and send appropriate responses
func responder(data chan string) {
	for {
		request := <-data
		fmt.Printf("%s ", request)
		switch request {
		case "ping":
			data <- "pong"
		default:
			data <- "huh?"
		}
	}
}

Aggressively minimalist

“what? how can you have a testing package with no assert functions?!?”

easy... you just don't have them! (if you want them, you're a grown-up: you can write them)

the case against

One hacker's opinions

One hacker's opinions (2)

Where next?

/