A journey in software development.

Or, how to do what you want and get away with it.

17 March 2017

Dmitri Shuralyov

Video

A video of this talk was recorded at University of Ontario Institute of Technology (UOIT) on March 17, 2017.

Video: www.youtube.com/watch?v=XSd9OAHVXMI

2

Programming languages

Which ones have you used? Heard of?

Which ones do you like?

What about frontend?

3

Programming languages

Preface:

4

Go

5

Go

You may have heard of Go.

It's my favorite language. I think you'll like it, too.

6

What is Go?

An open source (BSD licensed) project:

7

Go is about composition

Go is Object Oriented, but not in the usual way.

The result: simple pieces connected by small interfaces.

8

Go is about concurrency

Go provides CSP-like concurrency primitives.

The result: comprehensible concurrent code.

9

Go is about gophers

Go gopher by Renée French.
10

Core values

Go is about composition, concurrency, and gophers.

Keep that in mind.

11

Hello, Go

package main

import "fmt"

func main() {
    fmt.Println("Hello, Go.")
}
12

Hello, web

package main

import (
    "fmt"
    "log"
    "net/http"
)

const listenAddr = "localhost:4000"

func main() {
    http.HandleFunc("/", handler)
    err := http.ListenAndServe(listenAddr, nil)
    if err != nil {
        log.Fatal(err)
    }
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, web.")
}
13

Hello, net

package main

import (
    "fmt"
    "log"
    "net"
)

const listenAddr = "localhost:4000"

func main() {
    l, err := net.Listen("tcp", listenAddr)
    if err != nil {
        log.Fatal(err)
    }
    for {
        c, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }
        fmt.Fprintln(c, "Hello!")
        c.Close()
    }
}
14

Interfaces

Hey neato! We just used Fprintln to write to a net connection.

That's because a Fprintln writes to an io.Writer, and net.Conn is an io.Writer.

        fmt.Fprintln(c, "Hello!")
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
type Writer interface {
    Write(p []byte) (n int, err error)
}
type Conn interface {
    Read(b []byte) (n int, err error)
    Write(b []byte) (n int, err error)
    Close() error
    // ... some additional methods omitted ...
}
15

An echo server

package main

import (
    "io"
    "log"
    "net"
)

const listenAddr = "localhost:4000"

func main() {
    l, err := net.Listen("tcp", listenAddr)
    if err != nil {
        log.Fatal(err)
    }
    for {
        c, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }
        io.Copy(c, c)
    }
}
16

Goroutines

Goroutines are lightweight threads that are managed by the Go runtime. To run a function in a new goroutine, just put "go" before the function call.

package main

import (
    "fmt"
    "time"
)

func main() {
    go say("let's go!", 3)
    go say("ho!", 2)
    go say("hey!", 1)
    time.Sleep(4 * time.Second)
}

func say(text string, secs int) {
    time.Sleep(time.Duration(secs) * time.Second)
    fmt.Println(text)
}
17

A concurrent echo server

package main

import (
    "io"
    "log"
    "net"
)

const listenAddr = "localhost:4000"

func main() {
    l, err := net.Listen("tcp", listenAddr)
    if err != nil {
        log.Fatal(err)
    }
    for {
        c, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }
        go io.Copy(c, c)
    }
}
18

"Chat roulette"

Let's look at a simple program, based on the "chat roulette" site.

In short:

19

Design

The chat program is similar to the echo program. With echo, we copy a connection's incoming data back to the same connection.

For chat, we must copy the incoming data from one user's connection to another's.

Copying the data is easy. The hard part is matching one partner with another.

20

Design diagram

21

Channels

Goroutines communicate via channels. A channel is a typed conduit that may be synchronous (unbuffered) or asynchronous (buffered).

package main

import "fmt"

func main() {
    ch := make(chan int)
    go fibs(ch)
    for i := 0; i < 20; i++ {
        fmt.Println(<-ch)
    }
}

func fibs(ch chan int) {
    i, j := 0, 1
    for {
        ch <- j
        i, j = j, i+j
    }
}
22

Select

A select statement is like a switch, but it selects over channel operations (and chooses exactly one of them).

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(time.Millisecond * 250)
    boom := time.After(time.Second * 1)
    for {
        select {
        case <-ticker.C:
            fmt.Println("tick")
        case <-boom:
            fmt.Println("boom!")
            return
        }
    }
}
23

Modifying echo to create chat

In the accept loop, we replace the call to io.Copy:

    for {
        c, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }
        go io.Copy(c, c)
    }

with a call to a new function, match:

    for {
        c, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }
        go match(c)
    }
24

The matcher

The match function simultaneously tries to send and receive a connection on a channel.

var partner = make(chan io.ReadWriteCloser)

func match(c io.ReadWriteCloser) {
    fmt.Fprint(c, "Waiting for a partner...")
    select {
    case partner <- c:
        // now handled by the other goroutine
    case p := <-partner:
        chat(p, c)
    }
}
25

The conversation

The chat function sends a greeting to each connection and then copies data from one to the other, and vice versa.

Notice that it launches another goroutine so that the copy operations may happen concurrently.

func chat(a, b io.ReadWriteCloser) {
    fmt.Fprintln(a, "Found one! Say hi.")
    fmt.Fprintln(b, "Found one! Say hi.")
    go io.Copy(a, b)
    io.Copy(b, a)
}
26

Demo

27

Error handling

It's important to clean up when the conversation is over. To do this we send the error value from each io.Copy call to a channel, log any non-nil errors, and close both connections.

func chat(a, b io.ReadWriteCloser) {
    fmt.Fprintln(a, "Found one! Say hi.")
    fmt.Fprintln(b, "Found one! Say hi.")
    errc := make(chan error, 1)
    go cp(a, b, errc)
    go cp(b, a, errc)
    if err := <-errc; err != nil {
        log.Println(err)
    }
    a.Close()
    b.Close()
}
func cp(w io.Writer, r io.Reader, errc chan<- error) {
    _, err := io.Copy(w, r)
    errc <- err
}
28

Demo

29

Next steps

Want to see WebSockets, markov chains, learning bots, TCP and HTTP at once?

Video: vimeo.com/53221560

Slides: talks.golang.org/2012/chat.slide

30

Journey

31

Journey

Started programming at 14.

Excited by the ability to create video games.

32

Journey

33

Journey

34

Journey

35

Journey

36

Journey

37

Journey

38

Journey

Moved towards C++ because it's fast, cross-platform, compiles native binaries.

39

Journey

Master's degree.

40

Journey

I realized I wanted to create tools that help people (more directly than games).

Also grew frustrated with C++, extremely motivated to do something about it.

41

Journey

Bret Victor gave an incredible talk on following a guiding principle.

Video: vimeo.com/36579366

42

Journey

Started to work on an experimental project.

twitter.com/shurcooL/status/173110768726839296
43

Journey

44

Journey

Submitted it to a Live Programming Contest at LIVE 2013 Workshop. Won 1st place.

45

Journey

Got to visit San Francisco.

46

Journey

47

Journey

48

Journey

It helped me land my first job at a startup in San Francisco.

49

Startup life

50

Startup life

51

Hiring is hard

Startups with lots of raised money are bottlenecked on people.

A real-life story about a star.

52

Hiring is hard

53

Hiring is hard

54

Hiring is hard

55

Hiring is hard

56

Hiring is hard

A story about a talented engineer's ups and downs.

57

Open source

I like open source because people aren't locked out from being able to contribute.

58

Open source

59

Open source

60

Open source

61

Open source

It's normal to start small to test the waters.

62

Go community

Go is probably my first programming language experience with a "community".

There are conferences, meetups, talks, slack group, etc.

63

Go community

64

Go community

65

Now

Working full time on open source. Including personal projects (Go Package Store, etc.).

Contributing to Go, GopherJS.

First half of 2017, I'm prioritizing things I think are important (WebAssembly, etc.).
Second half, I'll be prioritizing ideas that can lead to profitability/sustainability.

66

Bonus: Browsers and Go

67

Browsers

I want to use Go, but it's hard to ignore the browser in 2017.

68

Go cross-compilation and wide platform support

Go already runs on many platforms.

# Desktop OSes.
GOOS=darwin  GOARCH=arm64 go build
GOOS=linux   GOARCH=amd64 go build
GOOS=windows GOARCH=arm64 go build

GOOS=plan9 GOARCH=amd64 go build  # Plan 9.
GOOS=linux GOARCH=s390x go build  # Linux on IBM z Systems.

# Mobile OSes.
GOOS=darwin  GOARCH=arm64 go build  # iOS.
GOOS=android GOARCH=arm   go build  # Android.
69

Go cross-compilation and wide platform support

Go already runs on many platforms.

70

Go cross-compilation and wide platform support

How about one more?

71

GopherJS

GopherJS is a compiler that compiles Go to JavaScript, which runs in browsers.

72

Want to see more?

Video: www.thedotpost.com/2016/10/dmitri-shuralyov-go-in-the-browser

Slides: dmitri.shuralyov.com/talks/2016/Go-in-the-browser/Go-in-the-browser.slide

73

Thank you

Use the left and right arrow keys or click the left and right edges of the page to navigate between slides.
(Press 'H' or navigate to hide this message.)