Error ? • The Applied Go Weekly Newsletter 2025-02-02
Your weekly source of Go news, tips, and projects
Error ?
Hi ,
Go's error handling has always been an easy target for criticism. The philosophy behind Go's "errors are values" concept is that errors should be treated seriously, rather than just an annoying edge case that hopefully is never going to happen. Still, Go's very explicit error handling rubs some developers the wrong way. Specifically, every if err != nil
block adds noise to the "happy path" of the code.
In the spotlight, I comment on a discussion that may (or may not) result in a proposal for a new error handling syntax. What do you think? Does the increased conciseness of the proposed syntax justify such an invasive change to the core language?
Featured articles
Go 1.24's go tool
is one of the best additions to the ecosystem in years · Jamie Tanna | Software Engineer
If you want to include specific versions of tools into your project, you have to employ a hacky solution with a tools.go
file with build constraints and whatnot. Go 1.24 includes a go tool
command that does away with such hacks.
Exploring the new "go tool" support in Go 1.24 | howardjohn's blog
Another go tool
intro, with an eye on execution speed.
Getting Started with Encore.go
Encore is a Go and TS framework for rapid application development. In December 2024, the company announced the separation of the Encore framework and Encore cloud. This was enough reason for Elton Minetto to get his feet wet.
Podcast corner
Cup o' Go
Due to closing the doors earlier than usual for this week's issue, I have no information about the latest Cup o' Go episode, but when this issue reaches your inbox, the new episode is certainly listed on their website.
Spotlight: A new error handling syntax
Proposals for new error handling syntaxes are a dime a dozen, but this one is different:
Ian Lance Taylor, member of the core Go team, created a proposal that's been turned into a discussion shortly after:
discussion: spec: reduce error handling boilerplate using ? · golang/go · Discussion #71460
No, there is no word missing, the question mark is the item that shall reduce boilerplate. In a nutshell, the new syntax looks like so:
For functions that return a result and an error:
// proposed syntax:
r := SomeFunction() ? {
return fmt.Errorf(...)
}
// shall replace (existing syntax):
r, err := SomeFunction()
if err != nil {
return fmt.Errorf(...)
}
For functions that only return an error:
// proposed:
SomeFunction2() ? {
return fmt.Errorf(...)
}
// shall replace:
if err := SomeFunction2(); err != nil {
return fmt.Errorf(...)
}
For functions that return an error that shall be passed to the caller unwrapped:
// proposed:
SomeFunction2() ?
// shall replace:
if err := SomeFunction2(); err != nil {
return err
}
Special case, as err
can be treated as an expression statement whose last value is of type error
, for cases where the error test is not adjacent to the error-producing function(s):
// proposed:
err ? {
return fmt.Errorf(...)
}
// shall replace:
if err != nil {
return fmt.Errorf(...)
}
I won't take sides. I am fine-ish with the old and the new syntax. If you're still unsure how this syntax affects real-life code, Ian converted the complete standard library to the new syntax so you can see for yourself:
all: demonstration of new error handling syntax for #71203 (644076) · Gerrit Code Review
(Line 124 in cover.go, for example, demonstrates the use of err ?
.)
What I'm worried about is a shift in behavior resulting from the new syntax.
The problem? Naked returns become far too easy:
someFunction() ?
I wouldn't want to see codebases where errors just bubble up, from the low-level source of the error to the top where it gets logged.
Here is why: Years ago, when I worked in tech support, customers reported an error in their log files that said,
Generic SSA NOTOK
There was no context, nothing whatsoever that could reveal the reason for this error. So I turned to someone from the engineering team and asked him to help me understand what kind of malfunction triggers this error message.
He replied that the error is very well known to them, but it is called from many different parts of the application, hence he cannot determine the specific circumstances that run into this error.
The last thing I'd want to see in a Go app is the equivalent of "Generic SSA NOTOK". As Go developers, we need to get into a habit of consciously determining if a given error needs to be passed along with contextual information.
I'm not saying that each and every error must be wrapped before returning, but as a bare minimum, errors should be wrapped if they occur at the boundaries of your code; that is, where your code calls other code or returns values to other code.
- Inbound boundary: A call into a library or an external API returns an error.
- Outbound boundary: Your library code returns an error to a caller.
In both cases, wrap the error with contextual information before passing it on.
What happens within your code is up to you. If your code contains internal call chains, no matter how long, it is ok if you let errors just bubble up internally, as long as the error carries enough context to enable you to track it down.
Quote of the Week: Finally! DeepSeek proves that optimizing software is possible
DeepSeek does optimization. The rest of the world is like… “wait?! We can optimize software to run faster on hardware?!?”
Tech is a joke. I don’t even have to draw a cartoon.
More articles, videos, talks
Five features in Go 1.24 - YouTube
Learn about these new features in Go 1.24: Generic type aliases, weak pointers, the go tools
command, new functions in bytes
and strings
, and the omitzero
tag for JSON marshalling.
Performance optimization in Go: Checkmate Performance using Chess Piece Movements as an example | by Ajitem Sahasrabuddhe | Jan, 2025 | Medium
Don't judge the article by the intro paragraph that reads like written by an LLM. The rest of the article is an interesting "log book" of optimizing Go code.
Greg Weber Blog • Success with errors in Go: stack traces and metadata
Standard error handling in Go is already quite powerful and versatile, but error handling libraries can still add some power on top.
Alibaba, Datadog, and Quesma Join Forces on Go Compile-Time Instrumentation | OpenTelemetry
If you want to use OpenTelemetry in Go, you either have to inject eBPF hooks into the binary or explicitly use OT packages in your code. A new standard for compile-time instrumentations shall improve this situation. Two proposals are on their way.
Abang Translator - Google Workspace Marketplace
A little success "story": Relatively new to Go, Muhammad Dyas Yaskur developed a chat translator app that has 167K downloads as of this writing. Source code. A small downside: Instead of making him money, the app costs money as it reaches out to paid translation services (first Google Translate API, now OpenAI’s GPT-4o-mini, which is more affordable). I hope the author soon finds a way of monetarizing his app (or, at least, loading off the API costs to the users).
Atomic Operations Explained: From Hardware to High-Level Code (using Go) | by Rohan Reddy Alleti | inspiringbrilliance | Jan, 2025 | Medium
If you write concurrent code, do you use (a) channels, (b) mutexes, or (c) sync/atomic
? Rohan Reddy Alleti explores the use of atomic operations.
Golang Benchmarking, Part 1 | francoposa.io
If you don't know how to run benchmarks on your code, you won't know if your optimizations are effective. – An introduction.
Projects
Libraries
GitHub - amanbolat/ft: Logs, traces and metrics for any function
Inspect functions in vivo with this tracing package.
GitHub - egregors/sortedmap: Effective sorted map for Go
Maps typically don't sort their entries. sortedmap
was made for those use cases where you actually want the map to be sorted by key or value.
GitHub - lucas-jacques/modb
MODB is an ORM built on generics without reflections, intended for everyday's CRUD operations.
GitHub - 39george/authpher: User identification, authentication, and authorization for Go
An HTTP auth middleware inspired by Rust's axum-login
crate. Authper uses alexedwards/scs for session management by default, but you can use a custom solution as well.
GitHub - cohesion-org/deepseek-go: A Deepseek wrapper written for Go supporting R-1, Chat V3, and Coder.
While the official OpenAI package has issues with multiple round conversations, the author decided not to wait on a fix nor to try contributing to that huge project, but rather roll their own DeepSeek package.
Tools and applications
GitHub - KhushPatibandha/Kolon: Strongly and statically typed interpreted language written in golang.
Maybe another programming language isn't what your looking for, but maybe you want to write a compiler for yourself and want to see how others do it. Then Kolon is for you.
Or you might just want to read the hilarious comments on the announcement in /r/golang.
GitHub - BelkacemYerfa/GOTS: A little transpiler to generate interface types from go struct types
Automatically turn Go structs into TypeScript interfaces and make integrating Go backends with TS frontends easier with GOTS.
Completely unrelated to Go
How might AI change programming?
AI can generate code from natural-language description, review code, and (with tools support) even actively influence the development and deployment workflows. Optimists love their new "assistant" while pessimists fear being replaced entirely. Thorsten Ball goes beyond this dualistic debate and thinks up other ways in which AI might change programming. What's your take?
DeepSeek R1 is good enough
Xe Iaso looks into DeepSeek's model architecture, the company behind it (and the fact it's not a state-controlled company), AI slop, and links to further interesting reads.
Second Principles
First Principles Thinking (FPT) is widely considered a preferable way of accumulating high-quality knowledge. Elliot Smith argues that FPT tends to build a mental model of the world too early. When faced with reality, the model turns out to be incomplete and, therefore, quite useless. Instead, Elliot turns the steps of learning around and starts with using whatever the best practices for a given task are, thus building on existing wisdom first and exploring the backgrounds later.

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