Learning Go with flashcards and spaced repetition

June 16th 2015 Nicola Paolucci in Golang

This year I have been choosing Go for all my coding projects. Go is brilliantly fast, simple to pick up, it has a powerful concurrency model based on message passing, and no forced - always on - object orientation. My impressions are similar to the ones many have previously articulated well - for example see "Go is unapologetically flawed..." or the hilarious "Four Days of Go". Add to those a fair bit of gesticulation and enthusiastic jumping around and you get what I think.

So far in Go I wrote an image collection scanner that uses perceptual hashes to find similarities and duplicates, a few web back-ends for React applications, the prototype of a task tracking tool based on the autofocus methodology, and a bot that monitors real-time Google Analytics data to notify my team on HipChat rooms for relevant events.

(I'll mention in passing that writing Bots for HipChat is disarmingly simple and rewarding. The bot above was written during one of our internal Hackathons using a tiny go package called hipchat-go).

As my knowledge of the platform grows, I am adopting more and more concurrent programming patterns that suit the language so well.

Using Flash Cards to learn Go

Spaced repetition and learning

Like with anything, growing a solid knowledge of a language requires time and the ability to absorb new APIs and libraries so that they become second nature. Here's what I've been doing on this front to deepen my command of the language. A couple of years back Derek Sivers wrote about "Memorizing a programming language using spaced repetition software"; that idea really got me intrigued.

The point is to use flash cards software to learn a programming language. You craft your own cards organically as you learn new things about the language and you end up with a completely customised path to proficiency. So I setup up Anki and have been following the routine that follows.

anki screenshot

If during a coding session I stumble on a small chunk of API, library, or best practice that I don't know yet I look up the answer - many times Stack Overflow has a perfect match for my search - and I summarise it into a simple Flash card. This way I can test my knowledge about it later and slowly move the information into my long-term memory.

Spaced repetition and learning Spaced repetition and learning

Go knowledge bytes

Here is a sampling of the cards I have added over time, about things that are easy to do but that I used to nevertheless have to look up every time.

How do you convert a string to a byte array?

[]byte("string")

How do you print Unix epoch number as string?

import "fmt"
fmt.Sprintf("%d", time.Now().Unix())

How do you write a string to a file?

import "ioutil"
ioutil.WriteFile(path, []byte("string"), 0644)

How do you create a directory?

import "os"
os.Mkdir(folder, 0755)

How do you read a whole file?

import "ioutil"
content, error := ioutil.ReadFile(path)

How do you sleep for x seconds?

import "time"
time.Sleep(time.Duration(3) * time.Second)

How do you parse a JSON string with an array of ints?

import "encoding/json"
var ids []int
err := json.Unmarshal([]byte(jsonString), &ids)

Can you convert to JSON a map[int]string ?

No, keys in maps can only be marshalled/un-marshalled if they are strings. map[string]string works.

How do you check if a map has a certain key?

if _, ok := map[key]; ok {}

How do you sort an array?

Define a custom type:

type ByTime []os.FileInfo

Implement 3 methods:

func (a ByTime) Len() int { return len(a) }
func (a ByTime) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByTime) Less(i, j int) bool { return a[i].ModTime().Unix() > a[j].ModTime().Unix() }

Finally use like this:

sort.Sort(ByTime(fileList))

How do you capture Control C before exiting?

import "os"
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
    for range c {
        //do something here
        os.Exit(0)
}()

How do you delete a file?

import "os"
os.Remove(path) error

How do you define command line flags?

import "flag"
var (
    port = flag.String("port", "8080", "web server port")
    static = flag.String("static", "./static/", "static folder")
    config = flag.String("config", "config.json", "path to config with all credentials")
)
flag.Parse()

Conclusion

I can share my flash card deck export if there is any interest but I assure you that if decide to take on this technique you should build your own cards organically over time, the value you will get from spaced repetition will be tremendously enhanced. Thanks for reading this far and if you like these sorts of random tangent dives follow me @durdn and @atlassiandev on Twitter.