Goto considered harmless • The Applied Go Weekly Newsletter 2024-02-18
Your weekly source of Go news, tips, and projects
What's your best practice for writing HTTP servers? I bet there are as many opinions on good HTTP server design as there are Go developers. But there's nothing wrong with learning from experienced Gophers.
Speaking of best practices, maintaining a low number of dependencies is not just a pointless demand by stubborn minimalists, nor is it an embodiment of the 'Not Invented Here' syndrome. Reducing the amount of third-party code in a project has undeniable advantages.
Best practices part 3: Using goto
is certainly not a best practice in modern software development — on the contrary, goto
obfuscates the execution flow and is only good for creating spaghetti code. Or maybe not?
And it's definitely a best practice in newsletter writing to not bore the readers to death with lengthy introductions. So let's move on to the featured topics of this week: HTTP servers, dependencies, and goto
.
How I write HTTP services in Go after 13 years | Grafana Labs
Mat Ryer can't stop writing HTTP services in Go.
How I write HTTP services in Go after 13 years | Grafana Labs
Reducing Go Dependencies
Too many dependencies in a project can be a maintenance burden as well as a security risk. In this case study, Daniel Taylor explores how to reduce dependencies in Go projects.
Give Go's goto a retry
Unpopular opinion: The goto
statement is underrated. Case in point: The standard library contains 603 goto
s.
Podcast corner
go podcast()
Using TDD is a no-brainer, or is it? Dominic St-Pierre has a use case for not using TDD.
go podcast() | 028: To TDD or not... or when
Cup o' Go
The latest news about Go proposals, Go 1.22, and more. Plus an interview with Daniel Martí, "maintainer at CUE, nerd sniper with Go." (Self-description)
Cup o' Go | slices.Pete and slices.Repeat sat on a fence
Go Time
Matt Ryer hosted the Gopher Say game on GopherCon EU. Here is the live recording.
Go tip of the week: The address of a zero-sized variable
Can the addresses of two variables be equal and different at the same time?
The following code defines a global variable a
and a local variable b
inside main()
. It then prints the addresses of both variables and finally compares the addresses.
The comparison should evaluate to true
, correct?
var a struct{}
func main() {
var b struct{}
fmt.Printf("&a: %p\n", &a)
fmt.Printf("&b: %p\n", &b)
fmt.Println("&a == &b:", &a == &b)
}
(Run the code in the playground.)
Here is the output:
&a: 0x58e360
&b: 0x58e360
&a == &b: false
Huh? Wot? Waitaminnit!
The addresses are definitely identical, so how can the comparison evaluate to false
?
Consider that a
and b
are empty structs. Empty structs have a size of zero, hence they don't need to occupy any memory cells. They would not even need to have an address at all. So comparing their addresses makes no sense to begin with.
In fact, the Go spec says (in section Comparison Operators),
"Pointers to distinct zero-size variables may or may not be equal."
So the value of a pointer to a zero-sized variable is completely undefined. But then, why do the address operators &
return an address at all?
The reason is that the address operator &
has no special value or status for "this variable has no address in memory". Returning nil
would not work either, because nil
means that the pointer does not point to any particular variable (but our pointers do!). So the Go compiler formally assigns zero-sized variables an address for the sake of not having to introduce the special case of "no-address" variables. The compiler might decide to even assign them the same address, because for zero-sized variables, it does not really matter what formal address they have.
The Go spec says:
"Two distinct zero-size variables may have the same address in memory."
I bet if you work with empty structs, you wouldn't ever feel the urge to get their "addresses", let alone compare two of those "addresses". But it may be worth keeping in mind that the Go compiler does not stop you from doing that.
Quote of the week: Complexity is not sophistication
Increasingly, people seem to misinterpret complexity as sophistication, which is baffling — the incomprehensible should cause suspicion rather than admiration.
– Niklaus Wirth
More articles, videos, talks
"Sub-feature": Go 1.22 and HTTP routing
So many articles on the new HTTP routing have been published this week that I decided to give them a designated section.
Routing Enhancements for Go 1.22 - The Go Programming Language
The "official" introduction to the enhancements for ServeMux
in Go 1.22. – By Jonathan Amsterdam.
Routing Enhancements for Go 1.22 - The Go Programming Language
URL path parameters and variables in Go (Golang) 1.22 and later
The new Go 1.22 routing wildcards explored. – By Willem Schots.
URL path parameters and variables in Go (Golang) 1.22 and later
New HTTP Router in Go 1.22
How exactly did we do routing before Go 1.22? - By Samuel.
Go 1.22's HTTP Package Updates
A specific look into the new routing features. - By KungFuDev.
Go 1.22's HTTP Package Updates
And even more articles...
Geez, people were really, really productive this week.
Go can only read 1GiB per Read call
Kashyap Kondamudi dug into the reasons
os.File.Read()
has a limit of 1 GiB, even though the limit at OS level is 2 GiB.
Questioning Go's range-over-func Proposal
Is the rangefunc concept too convoluted to be a nice fit for Go? Richard Ulmer thinks so. "To implement a function, that can be used in a range loop, you must implement an (ideally generic) function that returns a function which accepts a function as a parameter. This makes my head spin. I don't really want to imagine debugging range-over-func code." I think he has a point. Mentally deciphering the resulting execution flow from that construct is not for the faint of heart.
How to create thin stack traces à la Upspin. – By Redowan Delowar.
Golang: to Point or not to Point!
The concept of pointers is (a) easy, (b) difficult. If you switch to Go from a pointerless language, you might tend towards the (b) camp. But pointers aren't that difficult, once you wrap your brains around them. Homayoon Alimohammadi helps you with this in-depth discussion of pointer behavior in Go.
Static Assert in Go | zephyrtronium
Static assertions are assertions about specific properties of code that are verified at compile time. Branden J Brown demonstrates how to use constant expressions to make the compiler throw errors if certain assumptions about the code are not met.
Caveat: Some say the Tiobe index is based on an algorithm that generates skewed data.
A Markdown-first documentation workflow tool.
Go 1.22 is bringing about a new future for the language. - YouTube
Go 1.22 in less than 5 minutes.
Shifoo - Multi View Interfaces in Bubble Tea
How to switch between two or more screens in a TUI app using the Bubble Tea library. – By Lucifer "Bobby" Reeves.
TinyGo LEDs: 6-bit colors and Gamma Correction by zegl
Achieve big things on a tiny Raspberry Pico microcontroller, such as controlling 1024 RGB LEDs on a 32x32 matrix.
Go 1.22's go/types Alias type shows the challenge of API compatibility
TL;DR: If Go adds a new type, exhaustive type switches stop being exhaustive, until someone comes along and fixes them. But this requires to be aware that (a) Go added a new type and (b) one's code contains exhaustive type switches. – By Chris Siebenmann.
Understanding a recent optimization to Go's reflect.TypeFor
Or: how to speed up the new
TypeFor()
function by doubling the amount ofTypeOf()
calls inside. – By Chris Siebenmann.
Go (LEFT) CUE: Shifting Go left with CUE - Roger Peppe
Roger Pepe on how CUE, the configuration language that is its own schema language, can "shift" designing Go types to an earlier stage of development, therefore reducing risks (and increase the joy).
Last week's issue featured the article Retry function in Go. Xe Iaso takes this one step further and thinks about adding a retry mechanism directly to the language.
Projects
Libraries
GitHub - gen2brain/avif: AVIF image decoder
Image decoding seems to become a trend. Here is a package for decoding the AV1 image file format.
GitHub - gen2brain/jpegxl: JPEG XL image decoder
JPEG-XL, the Image Format Of The Future That Is Being Ignored By Google Chrome™. Here is a Go package for decoding JPEG-XL, may it gently push the Chromium devs into the right direction. See also the Chrome extension "JPEG XL Viewer".
GitHub - aaydin-tr/kyte: MongoDB Query Builder for Golang
Build MongoDB queries the easy way, with struct schema support.
Numeric calculations come with some footguns, like
1/3*3
not returning1
but0.99999...
. Symbolic Math circumvents such errors by treating1/3
as1/3
rather than0.33333....
.
GitHub - getsavvyinc/upgrade-cli: Upgrade makes it easy to add an upgrade
command to your go cli.
There may be reasons for not using
goreleaser
or other packaging workflows. In this case, adding a self-update subcommand to your CLI binary is a suitable alternative. Small drawback: it supports only GitHub repositories. (The base URL is hardcoded.)
GitHub - gorules/zen-go: Open-source business rules engine for Go
This business rules engine is written in Rust and provides native bindings for NodeJS, Python and Go. This repos contains the Go bindings. Find the rule engine itself here and a Web UI rules editor here.
Comes with a playground/demo page.
Tools and applications
GitHub - iliasgal/network-monitor: A Go-based tool for capturing and analysing network traffic
Capture network details and statistics. Not quite the next Wireshark, but certainly easier to use.
Another game made with Go & Ebitengine. The source code is availablehere.
GitHub - scmmishra/slick-deploy: CLI tool to declaratively deploy containers with Caddy
Zero-downtime deploys without the overhead of Kubernetes or the like.
GitHub - unagex/immudb-operator: Unagex Kubernetes Operator for immudb
ImmuDB is an immutable database (written in Go, BTW) for tamper-proof data storage based on Merkle trees. This k8s operator brings ImmuDB to Kubernetes by creating ImmuDB clusters, providing storage provisioning, and more.
GitHub - josephmate/EpicFreeGamesList: List of all free games from EpicGames so far
A project created for learning Go. The Readme includes some detailed learnings about fetching data from Epic Games (and how Cloudflare got in the way).
Features • GitHub Actions · GitHub
Reminds me of caarlos0/svu: Semantic Version Util.
GitHub - go-fuego/fuego: Golang Fuego - web framework generating OpenAPI 3 spec from source code
Similar to Huma but different in a couple of ways. GPL-licensed.
GitHub - galatolofederico/shieldsweep
Shieldsweep runs a suite of security tools for hardening your systems. (Use with care.)
decouple
finds overly specific patameters, such as anio.File
type that is only used toRead()
something and suggests using a more generic type (likeio.Reader()
in this example).
Completely unrelated to Go
From the moment I heard about Hashicorp's move to BSL and the resulting fork of Terraform named OpenTofu, I kept wondering what Mitchell Hashimoto, the founder and former CEO/CTO of Hashicorp, thinks about all this. Here is his answer, clear, unpretentious, and diplomatic.
Preventing security issues is also a matter of choosing the right language.
"No way to prevent this" say users of only language where this regularly happens - Xe Iaso
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