The Applied Go Weekly Newsletter logo

The Applied Go Weekly Newsletter

Subscribe
Archives
February 18, 2024

Goto considered harmless • The Applied Go Weekly Newsletter 2024-02-18

AppliedGoNewsletterHeader640.png

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.

Reducing Go Dependencies

Give Go's goto a retry

Unpopular opinion: The goto statement is underrated. Case in point: The standard library contains 603 gotos.

Give Go's goto a retry

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.

Gophers Say! GopherCon EU Athens 2024 with Wiktor + Diana + Greg vs Val + Andrii + Llwellyn (Go Time #303)

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.

New HTTP Router in Go 1.22

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.

Anemic stack traces in Go

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.

TIOBE Index - TIOBE

Caveat: Some say the Tiobe index is based on an algorithm that generates skewed data.

Hype Quick Start Guide

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 of TypeOf() 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).

I wish Go had a retry block

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.

GitHub - MatProGo-dev/SymbolicMath.go: A symbolic math module for the Go (Golang) Programming Language.

Numeric calculations come with some footguns, like 1/3*3 not returning 1 but 0.99999.... Symbolic Math circumvents such errors by treating 1/3 as 1/3 rather than 0.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.

GitHub - yohamta/gosbd: A sentence boundary disambiguation library for Go. It is rule-based and works out-of-the-box.

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.

Arctic Warfare by rocketnine

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.)

GitHub - bobg/decouple

decouple finds overly specific patameters, such as an io.File type that is only used to Read() something and suggests using a more generic type (like io.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.

Mitchell Hashimoto on X: "@ChiefScientist I’m not interested. It’ll only hurt someone’s feelings or cause drama, and a lot of the people on both sides are personal friends. I haven’t worked on TF for 4 or 5 years, haven’t been in leadership for 2 years, and now I’ve left. There’s no upside. Maybe in like 10 years." / X

° ° °

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.

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
This email brought to you by Buttondown, the easiest way to start and grow your newsletter.