If You Can Name It, You Can Tame It • The Applied Go Weekly Newsletter 2025-02-09
Your weekly source of Go news, tips, and projects
If You Can Name It, You Can Tame It
Hi ,
What's in a name? No, I'm not trying to get in a discussion about how to name your variables. This is the #1 unresolved problem in software development, and I'm not here to solve it.
Rather, I want to talk about using a name at all. Go allows defining anonymous types, but it's a bad idea to actually use anonymous type definitions, and in this week's spotlight, I explain why.
Enjoy this issue, and have a great week ahead!
– Christoph
Featured articles
Building Your Own Git from Scratch in Go | by Sarthak Duggal | Feb, 2025 | Medium
If you want to learn Git, read the Git book. If you want to really learn how Git works, build your own Git.
Real-Time Batching in Go | Viktor Nikolaiev's blog
Masses of data are best processed in batches. But how to turn real-time data streams into batches? Viktor Nikolaiev uses his concurrency toolkit rill
to turn irregularly arriving data items into rather regularly processed data batches.
How Are Images REALLY Stored?
In which Moncef Abboud explores the internals of various image formats and their use in Go.
All releases - The Go Programming Language
Security updates: Go 1.24rc3 and Go 1.23.6 have been released to fix a sidechannel timing issue in crypto/elliptic
and, for Go 1.24rc3, also an issue in the go
command of Go 1.24rc2 that allows executing arbitrary code when building a module containing CGO.
As always, get them while they're hot. 🍲
Podcast corner
Cup o' Go: Supply chain attacks ⛓️💥 Ghetto Logs 👊🏾 🪵 and Rust/AI cold takes 🧊 with Thorsten Ball
Special guest in this episode: Thorsten Ball, author of "Writing An Interpreter In Go" and "Writing A Compiler In Go" and currently working on Zed, an Electron-free, fast and lean VSCode alternative.
Spotlight: Avoid anonymous types
Anonymous types are types that are defined ad-hoc and have no name. Here is the start of a function that defines and uses an anonymous struct type:
func processAnonymousType() {
// Anonymous type defined inline
data := struct {
ID int
Value string
}{
ID: 1,
Value: "test",
}
// ...
}
Why is this problematic? Anonymous types –
- have poor reusability
- reduce code clarity in various ways
- are hard to refactor
Let's start with reusability. If you need the same type in another location, you need to replicate the complete type definition. Say, the function processAnonymousType()
continues with another data item. It needs to define the complete struct again:
func processAnonymousType() { // continued
// ...
// Need to repeat the anonymous type definition
var anotherData struct {
ID int
Value string
}
data = anotherData // Works, but type definition duplicated
// ...
}
The same applies to functions that take this anonymous type as a parameter. They need to replicate the function definition, making the function signature much more difficult to read (talking about code clarity!):
func processAnonItem(item struct {
ID int
Value string
}) {
fmt.Println("Processing anonymous item:", item)
}
Here is the definition of the same data structure as a named type, for comparison:
type DataItem struct {
ID int
Value string
}
And a counterpart to processAnonItem()
but with the named type DataItem
as parameter, that is much more readable:
func processItem(item DataItem) {
fmt.Println("Processing item:", item)
}
With a named type, reuse is simple and code becomes much clearer. In the following definition of processNamedType()
, reusing the type DataItem
in another place needs no duplication.
func processNamedType() {
data := DataItem{
ID: 1,
Value: "test",
}
// Reuse is simple
anotherData := DataItem{}
data = anotherData
processItem(data)
}
Go treats different named types as different, even if they are technically the same. For example, the type type pound int
is different from int
and cannot be passed to function expecting an int
type as parameter. This is important because, for example, a type type kilogram int
should not be used interchangeably, or failures analogous to the Gimli Glider incident may happen.
This safety net does not apply for anonymous types.
Continuing the processAnonymousType()
function, let's try to pass variable data
to processItem()
. Although the anonymous struct type and DataItem
have different type definitions, passing data
to processItem()
is possible:
func processAnonymousType() { // continued
// ...
processItem(data) //
}
Not only is this confusing but also obscures the relationship between different parts of the code: It's not obvious at first sight that the anonymous struct type used for data
is compatible with DataItem
and functions expecting this type.
In contrast to this, if you copy the DataItem
definition and rename it to DataItem2
, you cannot erroneously pass DataItem2
to processItem()
: The two types are different as pounds and kilograms are different.
type DataItem2 struct {
ID int
Value string
}
func processNamedType() { // continued
//...
data2 := DataItem2{}
processItem(data2) // Go disallows this type mismatch
}
What happens if you modify DataItem? For example, add a Count
field:
type DataItem struct {
ID int
Value string
Count int
}
As long as the existing fields aren't changed, you can still pass a DataItem
to processItem()
.
If you change the anonymous type in the same way, passing it to either processAnonItem()
or processItem()
would immediately fail with this error message:
cannot use data2 (variable of struct type DataItem2) as DataItem value in argument to processItem
Even the assignment data = anotherData
in processAnonymousType()
would fail. You'd just have signed up for a tedious refactoring process.
(Full code available on the Go playground.)
~ ~ ~
There are more disadvantages of using anonymous types; here is a summary of the drawbacks:
-
Poor reusability
- Anonymous types can't be referenced elsewhere in the code
- If you need the same type structure in multiple places, you'll have to repeat the type definition
-
Reduced Code Clarity
- Anonymous types make code harder to read and understand
- The type definition is embedded in the usage, which can make complex structures harder to follow
-
Documentation Challenges
- It's harder to reference anonymous types in documentation
- Anonymous types can't be directly documented using godoc
- They make API documentation less clear and harder to maintain
-
Testing Difficulties
- Testing code that uses anonymous types can be more complicated
- You can't easily create test fixtures or mock implementations
- Type assertions and comparisons become more verbose
-
Type System Clarity
- Named types make it easier to understand the domain model
- Anonymous types can obscure the relationship between different parts of the code
- They make it harder to maintain a clear type hierarchy
Bottom line: Avoid anonymous types; they can be intriguing for use in simple, one-off scenarios, but in general, they introduce more problems than they solve. Better get in a habit of always using named types to optimize maintainability, reusability, and code clarity.
Quote of the Week: On keeping code clear
Avoid, at all costs, arriving at a scenario where the ground-up rewrite starts to look attractive.
–qntm
More articles, videos, talks
How Databases Work Under the Hood: Building a Key-Value Store in Go | by Mohammed Galalen | Feb, 2025 | Medium
The simplest database is probably a key-value store. Hence it's a perfect subject for exploring database operations from scratch.
Go and DynamoDB: A Test-Driven Approach | Alpn Tech Blog
Pascal Sauerborn set out to write a test package for DynamoDB that is on par with moto
, a popular DynamoDB test library for Python.
pgx, database/sql transactions, and COPY · Dan Peterson
When you migrate from one DB module to another and discover that a handy feature is missing...
Recover panics in all Goroutines you start | Emir Ribic
Crash early, they say. Better your app crashes than continues from an undefined state, probably corrupting data on the way.
With concurrency, the same can be said for each goroutine. But does a crashing goroutine have to pull the whole app into the abyss? No, says Emir Ribic. Devs should learn a lesson from panic recovery middleware for net/http
and make their goroutines recover after a panic.
Go Supply Chain Attack: Malicious Package Exploits Go Module...
A malicious actor created a fake BoltDB module on GitHub. After the module got cached by the Go module proxy, the actor changed a git tag to hide the malicious code from code reviews.
The Go team reacted quickly and removed the cached module from the proxy.
Projects
Libraries
GitHub - voidDB/voidDB: A transactional key-value database written in Go for 64-bit Linux. Seemingly faster and more compact than lmdb-go, bbolt, Badger, and goleveldb. <2K LOC
This fast K/V store (benchmarks provided) requires 64-bit Linux as it uses open file descriptor (OFD) locks. The author explores options to add macOS and Windows OFD locks as well.
GitHub - imoore76/configurature: Simple, flexible, and powerful application configuration for Go.
App configuration via structs and field tags.
GitHub - theHamdiz/it: A collection of helpful error handling, performance measuring, execution retrial, benchmarking & other useful patterns for golang under one package.
Package author: "I made the most chaotic Go package ever and somehow got 8 stars? What?"
Well, as of this writing, the repo has 403 stars, so maybe check it out, if only for the fun of reading the README.
GitHub - ArFnds/godocx-template: Template-based docx report creation in Go
A templating system for Word! Write a Word document, insert template commands, and have your Go code replace the commands with actual text.
GitHub - rohankarn35/htmlcapture: htmlcapture – A Go package to capture high-quality screenshots from URLs, HTML files, or raw HTML strings. Supports dynamic HTML, CSS selectors, and Instagram-optimized sizes.
A chromedp-based screenshot library for HTML pages.
Tools and applications
Minesweeper by imprity
Sunday morning entertainment! A Minesweeper clone with really nice graphics.
GitHub - monasticacademy/httptap: View HTTP/HTTPS requests made by any Linux program
How to tap into a Linux command's HTTP requests without affecting the whole system? By using Go, gVisor, and linux network namespaces. It's as easy as that!
Zero-ETL Data Analytics with Postgres | BemiDB
Relational databases aren't suitable for use cases where fast processing of columnar data is paramount. BemiDB is a read replica for PostgreSQL databases that syncs PostgreSQL data to column-based storage, resulting in 2000x speedups for analytical queries.
GitHub - LandonTClipp/pciex: PCI Explorer
Explore your computer's PCIe topology with this Bubbletea app.
GitHub - unklnik/go-sdl2_isometric_deckbuilder_template: The beginnings of a pixel art, isometric deckbuilder game made with Go and SDL2
For anyone who wants to build an isometric deck-building game with Go and SDL2.
GitHub - QuangTung97/otelwrap: OpenTelemetry Go code generation tool
This tool generates OpenTelemetry wrappers for any interface.
GitHub - autopilot-team/interview: A production-like environment mirroring Autopilot’s internal stack, designed to evaluate real-world coding skills.
This repo is intended for interviews at Autopilot, but even if you have no plans to apply for a job, the repo is still good for studying a production-grade, full-stack app incorporating fine software engineering concepts like Database Migrations, Clean Architecture, Inversion of Control (IoC), Isolated Test Databases, API Gateway & gRPC Integration, Modern Frontend with React, orAutomated API Documentation.
GitHub - manuelarte/ghettoize_hook: 👊 Do you find boring to go through your logs? 👊🏿 Then this is the logrus hook that you are looking for
Logrus squad! 🙌 Tired of dem basic, repetitive error vibes? 🥱 Chill, homie: ghettoize_hook
gon’ flip ya lame
"Error: failed to connect to database"
into some lit
"Yo, dat database straight ghosted us, fam 💀".
Completely unrelated to Go
How to write a good design document
No, the answer is not, "pass the back-of-the-napkin scribbles to an LLM".
Summarizing our recommendations for software documentation
Software documentation is often neglected. These documentation tips help improve documentation processes and raise documentation quality.

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