Time is skipping • The Applied Go Weekly Newsletter 2024-12-15
Your weekly source of Go news, tips, and projects
Time is flying skipping
Hi ,
"Time flies like an arrow, but fruit flies like a banana." Unit tests should fly like arrows, but tests of timeouts fly like a grindstone. Go 1.24's synctest
experiment shall change this, as the first featured article explains.
Speaking of flying bananas time: The year is coming to an end, at least in countries using the Gregorian calendar. The Applied Go Weekly Newsletter goes into "winter break" mode from the following issue on until Jan 12th. This doesn't mean the issues stop coming; I'll be sending "Spotlight-only" versions during the winter break.
So no reason to go bananas. Enjoy the Holiday season!
Featured articles
Coming in Go 1.24: testing/synctest experiment for time and concurrency testing · Dan Peterson
So you want to test timings in the range of seconds but don't want to have your tests run for seconds? A remedy is on the way: Go 1.24 (due February '25) includes the testing/synctest
experiment that simulates the time that the tested code observes. Specifically, if all goroutines are asleep for, say, 5 seconds, synctest
advances the observed time by the sleep duration immediately.
Go 1.24 Release Candidate 1 is released
Related to the article above: Go 1.24 RC 1 is available for testing!
GitHub - cvilsmeier/go-sqlite-bench: Benchmarks for Golang SQLite Drivers
SQLite has a natural speed advantage over RDBMSs by requiring no network connection—it's an in-app library. But some use cases require squeezing the most out of the DB operations. A fast DB driver helps a lot. Spoiler: The fastest ones (for most of the tests) are two libs that aren't database/sql
compatible.
What's Missing From Golang Generics?
Did someone say, "This code looks like Java"?
Podcast corner
Cup o' Go: Update your crypto! And Go 1.24 preview
On crypto security, Go 1.24, weak pointers, compile-time auto-instrumentation, and rethinking DDD in Go.
Go Time: Pitching Go in 2025
Changelog have announced to drop Go Time, so this is probably the last episode, at least on this platform. I'm sure the Go Time team finds another home!
Spotlight: Spread the words: distributing a man page with Goreleaser and Homebrew
In the previous issue's Spotlight, I discussed a few options for writing or generating a man page for a CLI app. That's fine for having one locally, but how to distribute this man page to your app's users?
If you plan to distribute your CLI tool via go install
, you can have your binary install the man page on demand:
- Use a
//go:embed
directive to embed the man page in the binary - Add a flag to the tool that copies the man page to
/usr/local/share/man/man1/
and ensures that the file mode is0644
.
A nobler way of distributing an app is through package managers. There is a plethora of them, but luckily, there is also goreleaser
, a tool that builds releases of your CLI app and manages various package managers for you.
I wrote an introduction to goreleaser
on my blog, and a second part where I add Homebrew to my goreleaser
config. In these articles, I used the tool goman
that I wrote to fake man pages by grabbing the command's README instead. Now I am going to make goman
obsolete by telling everyone how to package real man pages alongside their tools! 😉
I won't go through all the steps of the articles again; please read the articles if you're new to either of goreleaser
, Homebrew, or goreleaser
's Homebrew integration.
In a nutshell, the goreleaser
config I built in the second article creates a new Homebrew tap called appliedgo/tools
, so that Homebrew users can install goman
as brew install appliedgo/tools/goman
.
Adding a man page to the Hombrew formula
The goal for today is to modify the goreleaser
config file to build the man page and have Homebrew install the man page along with the binary.
This turned out to be surprisingly easy.
Step 1: Build the man page
I decided to write the man page for goman
in Markdown and have pandoc
turn this into a man page.
goreleaser
has a pre-build hook that I utilized for running pandoc
. The original pre-build hook looked like this:
before:
hooks:
- go mod tidy
- go mod download
The before.hooks
property runs commands before the build, and I use this to tidy the dependency file and download missing ones.
For generating the man page, I only had to add this line to the list in order to invoke pandoc
:
- pandoc -s -t man goman.1.md -o goman.1
Step 2: Add the generated man page to the archive files
goreleaser
builds binaries for several OS/architecture combinations (based on what I told it). In the archives.files
property, I tell goreleaser
which files to zip up with the binary for getting released on GitHub:
archives:
files:
- README.md
- LICENSE*
Here, I added the generated man page:
- goman.1
Step 3: Ask Homebrew to install the man page
Finally, Homebrew must know that there is a man page to install. Homebrew makes installing man pages dead easy by providing a man1.install
directive that I added to goreleaser
's brews.extra_install
property. (The extra_install
property lets me add installation steps without overriding the whole installation procedure.)
brews:
- repository:
owner: appliedgo
name: homebrew-tools
# ...omitted for brevity...
extra_install: |
man1.install "goman.1"
(Fun fact: Homebrew formulas are Ruby code, and if you don't put the man page file in quotes, Ruby thinks goman.1
is a floating-point number and complains loudly.)
Wrapping all up
Now I only had to create a new Git tag, push the changes to the remote repo, and run goreleaser release
.
The goman.1
file is now included in all .gz
files of the release, and the Homebrew formula will install it to the appropriate man1
directory.
Now goman
behaves a bit more like a well-mannered Linux/macOS CLI tool. What's your next tool to equip with a man page?
Quote of the Week: Less documentation
The better the software, the less documentation it needs.
(Ideally, it needs just a man page, right?)
More articles, videos, talks
Go (Golang) Performance Benchmark (gnet vs fiber vs fasthttp vs net/http) - YouTube
HTTP routers aren't usually a performance bottleneck in Web apps. But for high-traffic web apps, you'd better pick a high-performance router. This video compares net/http
, gofiber
, fasthttp
, and gnet
.
Errors, Errors Everywhere: How We Centralized and Structured Error Handling | Oliver Nguyen
Go treats errors as values. And just like values, if you have too many of them, you'd want to organize them somehow. Oliver Nguyen presents a centralized error handling system that works with categories, tags, and error trees to avoid growing a hodgepodge of error handling approaches within a single app.
Nuage | Articles/Templ vs Gomponents
Which templating library should you pick? A shoot-out between Templ, Gomponents, or plain html/template
.
5 Mocking Techniques for Go | Golang Mocking for Unit Testing
Whatever your stance on mocking external dependencies in unit tests is, you should at least know the mocking techniques used in Go.
Enhancing Go performance: Profiling applications with flamegraphs | Costa on Software
There is NOT only one way to turn a performance profile into a flame graph.
Data structures as jigs for programmers (Go edition)
The author creates an interesting analogy between programming and woodworking to demonstrate how simple data structures like slices and maps can go a long way.
(Double points if you dance to an Irish or Scottish jig while reading the article.)
How to use migrations with Golang | ️Albert Colom
Program code and version control go well together, but what about database schemas? While a schema has a "code" representation, you need a way of up- or downgrading a database to a given schema version. This is where tools like golang-migrate
or goose
come in handy. Here is a hands-on tutorial.
Gist of Go: Pipelines
Anton Zhiyanov's interactive Go book is growing. Latest chapter: pipelines.
Organizing Your Go Code: Tips for Beginners
Remember: There is no single Go project file layout. Choose the layout that fits your use case. Start minimal; the layout will grow with your project.
Demystifying OTPs: the logic behind the offline generation of tokens
How does a One-Time Pad (OTP) work? Find it out by writing one in Go.
Things You Never Wanted To Know About Go Interfaces
Or maybe you want but you didn't know that you wanted?
Projects
Libraries
GitHub - xybor-x/enum: Elegant and powerful Go enums with zero code generation
Goals of this enum library are compatibility with iota
-style "enums", no code generation, and type safety (when giving up iota
compatibility).
GitHub - ymz-ncnk/go-client-server-communication-benchmarks: Compares the performance of several client-server communication libraries/frameworks for Golang
Which is faster, gRPC, Kitex, or cmd-stream-go?
GitHub - crazywolf132/conduit: Because life's too short for complicated socket programming!
Communication pipelines without the plumbing.
Tools and applications
GitHub - essentialkaos/aligo: Utility for checking and viewing Golang struct alignment info
For some apps, every byte of memory counts. aligo
helps optimize structs by visualizing their memory layout.
GitHub - Abathargh/stropt: C struct optimizer
This must be the week of struct optimizers. This issue lists a visual optimizer for Go structs elsewhere in the "Tools and apps" subsection, and here is a memory layout optimizer for C structs.
fontseca.dev — fontseca.dev's RPC-like API
Wow. A personal website built upon 70 API endpoints. Overkill? You decide. In any case, it's a great project for studying the GoTH stack (Go, Templ, HTMX) in real life.
GitHub - go-dockly/garm: Advanced ARM64 Compiler for High-Performance on the GO
The author wrote this ARM64 compiler because he was "unhappy with go's current state of Plan9 assembly mess and the many arm64 capabilities that remain untapped."
GitHub - armand-sauzay/note: ✍️ take notes in your terminal ✍️
Create and organize Markdown notes in your terminal. With Vim-style keybindings.
GitHub - MegaGrindStone/doconvo: A Terminal User Interface (TUI) application that enables interactive conversations with your documents using Large Language Models (LLM) and Retrieval-Augmented Generation (RAG) techniques.
Not every chatbot requires a web page.
Antonio Pitasi
A personal website built with GoTH... not! It's all standard library. (Source code here)
Completely unrelated to Go
"Rules" that terminal programs follow
While there is no strict rule set that CLI tools follow, a canon of rules or patterns emerged over time. If you plan to write an app, make sure to follow these patterns to delight your users.
Can Postgres cover your NoSQL needs? · Blog · Liip
For many backend devs, PostgreSQL is their go-to database in every situation. But can PostgreSQL even replace NoSQL databases?
Happy coding! ʕ◔ϖ◔ʔ
Questions or feedback? Drop me a line. I'd love to hear from you.
Best from Munich, Christoph
Not a subscriber yet?
If you read this newsletter issue online, or if someone forwarded the newsletter to you, subscribe for regular updates to get every new issue earlier than the online version, and more reliable than an occasional forwarding.
Find the subscription form at the end of this page.
How I can help
If you're looking for more useful content around Go, here are some ways I can help you become a better Gopher (or a Gopher at all):
On AppliedGo.net, I blog about Go projects, algorithms and data structures in Go, and other fun stuff.
Or visit the AppliedGo.com blog and learn about language specifics, Go updates, and programming-related stuff.
My AppliedGo YouTube channel hosts quick tip and crash course videos that help you get more productive and creative with Go.
Enroll in my Go course for developers that stands out for its intense use of animated graphics for explaining abstract concepts in an intuitive way. Numerous short and concise lectures allow you to schedule your learning flow as you like.
Christoph Berger IT Products and Services
Dachauer Straße 29
Bergkirchen
Germany