Everything

a.k.a LOL WAT?

What I plan to cover

  • Practicle Go
  • Effective Working
  • Debugging Process

Practical Go

useful bits from the last four years

SOLID Go Design

  • Talk and post by Dave Cheney
    • Keynote at GolangUK 2016
  • Go read and watch

Testing

  • Don't skip it because you are in a hurry
  • Gives you confidence to change your code
  • Write tests at the correct level
  • Most your tests should be unit tests
  • You do need functional / integration tests
  • Check your code coverage
    • go test -cover

Testing Repositories

  • gocheck​
    • gopkg.in/check.v1
    • way better than the built in standard library
    • provides test suites, asserts, and checkers
  • github.com/juju/testing
    • stand alone test library using gocheck
    • isolation and cleanup base suites
    • additional checkers

Get serious about logging

Asynchronous Go

  • Learn to use channels properly
  • Use sync.Mutex when necessary
  • Be careful with goroutine lifetimes

Parallel executing is hard

  • Just because you think something should be running before something else doesn't mean it will
  • Run tests with the race flag
    • go test -race
  • Avoid using time.Sleep and time.After in production code
    • timing issues between goroutines can be very hard to track down
    • consider a Clock interface, like the one defined in github.com/juju/utils/clock

Channels

  • Channels will block
    • even buffered will channels block
  • Never use naked channel reads or writes in production code

Naked Read / Write

func something(events <-chan event) {

    // prelude

    next := <-events

    // do something with next

}

Select Read / Write

func something(events <-chan event, done <-struct{}) {

    // prelude

    select {

        case next := <-events:

            // do something with next

        case <-done:

            return

    }

}

Interfaces are Great

  • Makes more sense to declare them where you need them
  • As a general rule:
    • Take interfaces as arguments
    • Return concrete types
  • Doesn't always work when you have nested types returning types, in which case, have those return interfaces

Memory matters

  • It matters much more in service oriented code
  • Just because Go is garbage collected doesn't mean you can forget about it
  • Learn how Go captures object references, and when things can be released

Effective Working

getting shit done

What is "work" for us?

  • Planning
  • Developing
  • Fixing

Planning

  • Create a prioritised list of features
  • Don't do too much in parallel
  • Size tasks and use that to help prioritise
  • Remember your key mission

Developing

  • Focus
    • Thrashing is bad, very bad
  • If you can, pair early on development
    • This shares knowledge and validates approach
  • Write tests
  • Code review
  • Feature flags are good, feature branches not so much

Developing a feature

  • Break the task down into pieces
  • Each piece should be no more than 2-4 days of work
    • preferably 2
  • Measure the development process
    • if someone is on a task that should only take two days, but is taking longer, go talk with them, or if it is you, seek help
    • either the approach is wrong, or sizing was misjudged and needs to be re-evaluated
  • Burn down charts of feature development can help motivation

Fixing - Bug squashing

  • You will spend more time fixing the bugs than writing the feature
  • Because of this, you will read your code much more than you write it
  • This segues nicely into the next topic

Debugging Process

what to do when you don't know what to do

Step One: Reproduction

  • It is almost impossible to fix an issue you can't reproduce
  • Sometimes reproduction depends on race conditions
    • The race detector is good, but doesn't find them all
  • Write a script to stress your tests
  • Sometimes you need to put your machine under load as well as stress, recompiling everything while running stress.sh works for me

Step Two: Identification

  • Remove assumptions
    • Log all your assumptions around the area of code
    • Use permanent trace logging, temporary error logging, or c.Logf
    • Sometimes you'll find the issue there
  • Log around the loops
    • simplify the boolean expressions
  • Issues are much more often bad assumptions than incorrect calculations

Step Three: Fix it

  • This is actually the easy bit

Question time

Made with Slides.com