Skip to content

Instantly share code, notes, and snippets.

@jasonkeene
Last active May 25, 2019 18:28
Show Gist options
  • Save jasonkeene/d0bb1375d78f8ece9814c48b785e5ce2 to your computer and use it in GitHub Desktop.
Save jasonkeene/d0bb1375d78f8ece9814c48b785e5ce2 to your computer and use it in GitHub Desktop.
Notes for the Programming Languages Club session on Go

Go is an imperative, compiled, statically-typed, garbage-collected, concurrent, general purpose programming language. It emphasizes fast compilation, fast execution, and a conservative, simple language design.

What is Go good for?

Server Software

Go has modern, native implementations of many networking protocols. Concurrency was a first class concern of the language. These features work very well with the highly concurrent nature of networked systems.

CLIs

Go is statically compiled. This means that the output of the compiler is a binary that contains all the bits of the program needs to run. It is very straight forward to cross-compile to other operating systems and architectures:

GOOS=linux GOARCH=arm go build
GOOS=windows GOARCH=386 go build
GOOS=darwin GOARCH=amd64 go build

This makes Go a great language to implement CLIs since you can distsribute binaries that are self-contained. Go has various packages to help with creating CLIs including cobra.

Large Complex Systems

Go was designed to work well with large code bases with many engineers. Compilation speed was a primary inspiration for the design of the language. I would also argue that the simplicity in the language design contributes to easier to understand code. There is no magic. What you see is what you get. However, I have seen some hard to understand code written in Go over the past few years, YMMV.

Highly Concurrent Systems

Goroutines allow for creation of light-weight threads of execution. Goroutine stacks are allocated on the heap and expand/shrink dynamically based on the needs of the executing code. It is practical to create hundres of thousands of goroutines in a single process.

Communication between multiple goroutines is acomplished either via channels or the built in sync package that provides implementations of mutexes, conditional locks, waitgroups, atomic operations, etc.

Data Science/ML/Data Processing

The gopherdata github org is a great place to start if you are interested in data science. Go doesn't have all the capability of Python when it comes to this field, however I think this is an area where Go shines. When developing models in Python you can get into situations where the data you tested your model on does not expose exceptional cases and when you run the model on production data it will break. Go forces you to think about these cases up front.

Robotics/Microcontrollers

Gobot is a popular framework for writing software that targets microcontroller and robotics platforms. They support many different hardware platforms. I imagine Go's ability to interop with C via cgo is also very helpful in this area considering most software in this space is implemented in C.

What is Go not great at?

GUIs

Go has a few options for doing GUIs on different platforms. However this is not an area where Go shines.

Mobile

Go has some support for mobile applications. There is not great library support however.

Frontend Web Development

Similar to GUIs and mobile, frontend web development is not Go's sweet spot. There are options to target the browser via wasm and gopherjs. The work being done here is actually quite interesting. I imagine most users are existing Go users that want to run in the browser. I don't see many frontend web developers choosing Go. There are some technical downsides as well as Go has to ship the runtime down to the browser. From what I understand there is not a way of re-using/caching this download, it gets shipped with every Go wasm program. The current implementation uses Go's garbage collecter. It would be ideal to leverage the existing GC built into browsers. There is work to be done.

Operating Systems/Drivers

Because Go is a GC'd langauge it is not a great fit for some systems programming such as Operating Systems or driver development. Incidentally gvisor is implemented in Go so it is possible to use Go for these applicaitons.

The Concurrency Story

Go's concurrency model is built aroud CSP (Communicating Sequential Processes). To quickly summarize, CSP is a system of passing messages between collaborating processes (not the OS kind).

| Share memory by communicating, do not communicate by sharing memory.

An example of this in Go:

ch := make(chan int)

go func(){
    for i := 0; i < 100; i++ {
        ch<-doSomeWork(i)
    }
}()

for d := range ch {
    process(d)
}

Weaknesses

  • Package Management
  • Generic Programming
  • error handling

Interesting Features

go

The go keyword spins up the proivided function in a new thread of execution.

go someFunc()
go some.method()
go func(){
    step1()
    step2()
}()

log.Fatal(http.ListenAndServe(":8080", nil))
go log.Fatal(http.ListenAndServe(":8080", nil))

defer

defer allows you to run a bit of code at the end of the function, no matter how the function exits. This is great for clean up. You can also use this to recover from panics.

defer file.Close()
defer func (){
    if r := recover(); r != nil {
        // recovered from panic
    }
}()
panic("error happened")

interface

Interfaces are sets of methods that a type has to comply with in order to be passed or assigned to a variable of that interface type. These differ from interfaces in Java in that you do not have to declare that your concrete type implements the interface. It either has the set of methods or it doesn't.

type Runner interface {
    Run() error
}

type runner struct {}

func (*Runner) Run() error {
    // ...
}

func doIt(r Runner) {
    // ...
}

var r Runner
r = runner{}
doIt(r)

chan

unbuffered := make(chan bool)
buffered := make(chan int, 100)

select

for {
    select {
    case v := <-ch1:
        doSomething1(v)
    case v := <-ch2:
        doSomething2(v)
    case v := <-ch3:
        doSomething3(v)
    default:
        time.Sleep(100*time.Millisecond)
    }
}

type embedding

type Foo struct {
    A int
    B int
}

func (*Foo) DoIt() {}

type Bar struct {
    Foo
    C int
}

Interesting Packages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment