The Applied Go Weekly Newsletter logo

The Applied Go Weekly Newsletter

Subscribe
Archives
February 10, 2025

If You Can Name It, You Can Tame It • The Applied Go Weekly Newsletter 2025-02-09

AppliedGoNewsletterHeader640.png

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:

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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.

Check it out.


Christoph Berger IT Products and Services
Dachauer Straße 29
Bergkirchen
Germany

Don't miss what's next. Subscribe to The Applied Go Weekly Newsletter:
LinkedIn
Powered by Buttondown, the easiest way to start and grow your newsletter.