
Advent of Code has been a December tradition for me for the last 5 years — I’ve posted before about why I like it so much — and I’m looking forward to 2025’s event starting soon. This year’s format has a few changes, to make it a bit less stressful for the organiser Eric Wastl, but still sounds fantastic. I’m amazed he’s still able to keep this running in his free time! Do send him some support if you can.
You can tackle advent of code using any programming language you like. Some people have gotten very creative with this, such as:
- A different language for every day of the challenge (including very unusual ones like Shakespeare)
- Only using spreadsheet functions
- Developing on an actual Commodore 64

For my part, I found just solving the puzzles to be enough of a challenge for my first few years and so I stuck to Python, a language I know well. After I learned plenty of maths, computing, and problem solving approaches, I switched to TypeScript, and now I’m moving on to Go. Using Advent of Code to learn these its lots of fun, but I’ll be honest — having a look at some of these more unusual ideas makes me tempted to try something more ambitious! Maybe I’ll look to overcomplicate things more next year.
For now, I’ll share just one more link: did you know some people solve the puzzles with Minecraft?
Why Go?
I’d heard of Go, but hadn’t looked at it at all until Chris Wilson talked me through what he likes about the language and how he’s been making videos about it on his Chris Do Dev channel. Reading further, I realised lots of major projects are written in Go, including Kubernetes, Terraform, Docker, and soon: A 10x faster TypeScript.
The thing that really caught my attention was who some of the Go designers were: Ken Thompson and Rob Pike are computing legends (UNIX! Plan 9 From Bell Labs! UTF-8! Regular expressions and so much more!). They’ve influenced so much of modern computing and shared lots of their thinking over the decades, and I was very keen to see how they’d approached this new language.
Reading Go at Google: Language Design in the Service of Software Engineering gives lots of useful background about why Go exists. Its origin story is that it was conceived during one of the 45 minute waits they regularly had for a C++ build at Google. Hearing about the challenges they had at Google’s huge scale — pulling in hundreds of dependencies, getting new joiners up to speed and productive, spotting the causes of bugs — is good context for understanding why Go eagerly marks unused variables and imports as errors, and why it proudly has a very limited set of keywords and ways to do things.
I also appreciated Rob Pike’s 2023 What we got right, what we got wrong talk, looking much wider than just the language itself, including reflections on the Go Gopher.

It’s an interesting approach: Go isn’t trying to be a one-size-fits-all language to use for everything, or to demonstrate any new and unusual language design ideas.
- It’s designed to be fast at building, fast at running (especially with CPU-bound tasks), and fast for people to learn and start contributing with.
- It’s simple to the point of “boring”, and encourages everyone to solve similar problems in similar ways — helping both computers and humans with the above goals.
- It’s made various choices about memory management and concurrency to help make them easy to work with, to help avoid whole classes of bugs and performance issues that were causing issues in Google’s large codebase.
Go makes a nice contrast to the last language I used for AoC:
- Lots of languages grow features and syntax over time — JavaScript today is very different than when I first learned it, and you can find all the “generations” of it in codebases and tutorials online. Go’s very clear about keeping the feature set small and maintaining compatibility.
- One of Go’s proverbs is “A little copying is better than a little dependency”, and it’s quite set against importing external packages unless you’re sure you need them. This seems very different than JS/TS where there’s an npm package for everything, each of which depends on many others … which can cause problems.
- I think a big motivator for Node’s popularity is that for web dev, you need to use JavaScript (or one of its adaptations) for browser-side work, and using it on the server means just one language is all you need to know. This is different than the “pick the best tool for different jobs” idea that makes Go’s design so specific.
- Go’s concurrency approach is quite different from what I’ve used to — and in his Concurrency is not parallelism talk Rob Pike says he’s really not a fan of the async/await approach and encourages everyone to read C.A.R. Hoare’s Communicating Sequential Processes paper, to understand where Go and some other languages take their ideas from.
This isn’t me saying Go’s made better choices on all (or any) of these topics — it’s more that it’s enlightening to see different approaches and learn more about their trade-offs.
How it’s Going
I’ve really appreciated the tutorials that come with Go: the Go Tour and lots of official tutorials helped me learn quickly, and there’s a nice focus on explaining idiomatic Go — “how people would expect you to do things around here” — in Effective Go and the Go Style Guide.
- A few features took me right back to writing C and C++ a long time ago — I haven’t seen the * and & of pointers or the “%s %d” of printf for a good 10 years — but they all seem sensible and usable.
- Go doesn’t have inheritance, just composition and interfaces — again, seems sensible so far. “Prefer composition over inheritance” has been standard advice for a long time, and the docs describe the problems they’re trying to avoid by leaving inheritance out.
- In general, Go’s very opinionated about formatting, and a gofmt tool corrects all your code on every save. I feel fine with this, I’ve never had much interest in tabs vs spaces style debates and appreciate getting boring questions out of the way!

I finished some of Advent of Code 2015 when learning TypeScript, and I’ve now wrapped up the last puzzles in Go. Have a look at my repo (with very beginner Go code) if you like.
When I did this in TypeScript, I had a go at emulating functional-style generator expressions like Python has — very fun for exploring the language, but surely confusing for any co-developers. In Go I’m sticking to more idiomatic, “unsurprising” code. I did have a look for similar packages in Go and found one from Rob Pike, who did it for fun like me and notes “you shouldn’t use it”.

Some things I’ve had fun reimplementing in Go
Some Python standard library functions (itertools.combinations and product) — these are straight ports of the Python docs’ pseudocode and I’ll tidy them up.
A priority queue, following a guide in Go’s container.heap docs. Here I struggle with some of Go’s testing style advice: they don’t like using xunit-style assertions, but surely this is a sensible way to test the queue’s working? I’ll keep playing with the standard Go style.
The A* algorithm, after spotting where a puzzle could use it and reminding myself how it works with my handy Shakey the robot blog post. I was pleased this worked for a puzzle that doesn’t immediately look like a graph.
And for a 2021 puzzle (I plan to get all the many AoC stars eventually), I was pleased to spot a chance to use memoization; this is like a magic trick that speeds up runtimes unbelievably. This version avoids the elaborate tricks I tried with TypeScript decorators, but I’ll keep playing with ways to make it readable and flexible.
More in December 2025…