FOSDEM 2025

Table of Contents

After years of thinking “I should have gone” after the fact, I finally went to FOSDEM!

FOSDEM—which stands for Free and Open source Software Developers’ European Meeting—is a free, no registration required, event held in Brussels each year. Thousands of developers gather there to connect and share ideas. This was the 25th edition.

Below are the notes I took during the talks I attended. The titles of the talks are links to the FOSDEM schedule. That is also where the recordings of the talks can be found once they are published.

The state of Go — Maartje Eyskens

This is the eleventh edition of the Go devroom at FOSDEM. It’s the first time the Go devroom is bigger than the Python devroom. (By the way: Rust has the biggest one this year.)

Go itself is 15 years now (so it is definitely not a new language anymore) and has had 25 point zero releases. Go has a stable API, a strong and stable standard library, dependency management and generics.

Go 1.23 was released on August 13th, 2024. Go version 1.24 will be released this month. So what has changed since last year? To name a few (Maartje mentioned more, but I wasn’t able to write them all down. Watch the recording if you want to see them all):

  • Language changes
    • Go can now loop over three new types
    • Generic types can now be used in type aliases.
  • Tools
    • go vet”: many new warnings
    • Go tooling now support JSON (e.g. “go test --json”).
    • Go sets binary version based on VCS: “debug.ReadBuildInfo()” (use “--buildvcs=false” to disable the dirty flag)
    • go tool”: add tools used in builds in go.mod.
    • Go telemetry is still opt-in. Use “go telemetry on” and “go telemetry off” to switch it on and off. The Go team believes that telemetry will play a critical role in helping Go development.
  • Standard lib
    • Several new helpers for iter functions
    • Support for quantum proof key exchanges
    • Bunch of modern algorithms (e.g. PBKDF2 and SHA3) moved to stable library
    • os.OpenRoot("path")” gives you a safe file system. Even protects against symbolic links outside of path.
    • JSON encoding supports new omitzero
    • New unique package for faster comparison.
  • Runtime
    • Swiss maps
  • Ports
    • Go 1.25 will require macOS Monterey or later
    • Go 1.24 has no support for Windows windows/arm
    • Go 1.24 requires Linux kernel version 3.2 or later (released in 2012)

Go conferences this year:

  • Go devroom @ FOSDEM 2025 (today)
  • Gophercon Latam Brazil (May 5–6)
  • GopherCon Europe Berlin (June 16–19)
  • Gophercon New York (August 26–28)

The Inner Workings of Go Generics — Anton Sankov

Generic allow you to work with different types, while keeping type safety.

Example:

func ToSlice[T any](a, b T) T[] {
  return []T{a, b}
}

intSlice := ToSlice[int](1,2)
floatSlice := ToSlice[float32](1.5, 2.5)

// Alternative, use type inference:
intSlice2 := ToSlice(1, 2)

// Type safety: this will NOT compile:
wrongSlice := ToSlice(1, "string")

Why was Go created:

  • Simplicity (over C++)
  • Fast compilation times (over C++)
  • Fast runtime (over C++)

Generics complicates all three. However, people started complaining about the lack of generics the day after Go was introduced to the world. Generics were proposed a bunch of times and only in 2021 a proposal was accepted.

The generic dilemma is this: do you want slow programmers, slow compilers and bloated binaries, or slow execution times?
—Russ Cox, The Generic Dilemma

None of the proposals contained an implementation. So more proposals were needed. Three proposals were written, and the last one was accepted: “GC shape stenciling”, which is a middle ground between stenciling (proposal 1, the C++ way) and dictionaries (proposal 2, the Java way).

Anton showed an example of how this works. See https://asankov.dev/go-generics/ for the slides, which includes a full example, or his GitHub repo: https://github.com/asankov/go-generics

This proposal still has some drawbacks though: a performance penalty in compile time and in runtime. However, there’s only little performance impact on compile time and usually only little performance penalty in runtime.

The exception to the latter is when you are passing interfaces to generic methods. In this situation, generics can have a big performance impact. If this matters to you: don’t use generics.

Picture comparing generics in C, C++, Java and Go

Anton comparing generics in different languages (image taken from his slides)

All in all, Go is in a good place with generics.

Swiss Maps in Go — Bryan Boreham

Swiss Map is a new map implementation in Go 1.24.

The name of the way it’s implemented is Closed Hashing. The story goes that this is where the name “Swiss map” comes from: CH is the country code of Switzerland.

There were lots of visuals in the presentation to explain how it works, which I found hard to take notes on that can be understood without copying the whole presentation alongside it. It was an interesting presentation, do watch the video if you want to know more about the topic.

Go-ing Easy on Memory: Writing GC-Friendly code — Sümer Cip

There’s a lot of theoretical info around garbage collection (GC), but less actual tips and tricks. This presentation aims to be as practical as possible.

An example of why this topic is important: Datadog switched from Go to Rust because their service spent 30% of CPU resources on GC (source).

Some of the tips from Sümer:

  • Reducing size almost always has compounding benefits
  • Returning escapes to heap, calling does not (note: stack is better than heap for performance)
  • interface{} and generics escape to heap
  • Avoid pointers! GC overhead is linear with the number of pointers.
  • Try keeping map key/values sizes under 128 bytes
  • “Copying is expensive” is a myth. Copying cache lines is the same as copying a pointer
  • Remember zero allocation libraries? Use them!
  • Reuse slices (e.g. a = append(a[:0], 10, 20) instead of a = append(a, 10, 20))
  • Tune GC by using GOGC and GOMEMLIMIT
  • Profile and benchmark your code

Execution tracer is an underrated tool. It’s a great cinematic visualization. It’s (kind of) safe to use on production: with Go 1.21 overhead drops to ~1-2%. For more information see More powerful Go execution traces

As always: for more tips, details and background information (e.g. on memory and garbage collection) watch the recording.

Other interesting talk: Make your Go Faster by Bryan Boreham, FOSDEM 2018.

Build better Go release binaries — Dimitri John Ledkov

The focus of this talk is on Linux binaries, but may also be applicable to other environments. It’s basically a list of tips. I wrote these down as reminders to later look into these in more depth.

  • go build -ldflags -w” to remove debug information—which is on by default—since it is often unused in production anyway but can be quite large in size.
  • go build -trimpath” to prevent leaking full file paths into the binary, to not take up space an not doing it leads to non-reproducible builds.
  • go build -tags netgo,osusergo” (for container/portable binaries, “CGNO_ENABLED=1 go build” for explicit host OS resolution)
  • GOAMD64=v2 GOARM64=v8.0” for production hardware that is not 20 years old, this will improve performance of your binaries
  • go build -buildmode=pie”: position independent code/executable can improve security. Use this for dynamic libraries.
  • go build -ldflags -X main.Version=$(git describe ...)
  • Go toolchain doesn’t respect CFLAGS/CXXFLAGS. Use CGO_CFLAGS, CGO_CXXFLAGS, etc.
  • Use “govulncheck -mode=binary” to report module level CVEs. If your binary has symbol tables, it reports symbol level CVEs. If you keep your symbols in your binaries, the vulnerability checker could check better if the vulnerability is actually affecting you.
  • Do not use “go build -ldflags -s” Do not use “strip --strip-all”. Verify with “go tool nm”.
  • Bump your “toolchain go1.x.y” stanza regularly. The same code built with a new go toolchain can be safer.

Kubernetes outside of the cloud: Lessons learned after 3 years — Nadia Santalla

For Nadia a self managed Kubernetes cluster, out of the cloud, is: managing your own hardware, managing your own control plane, and not relying on external services (like DNS).

A Kubernetes node is a properly configured and running kubelet process. A control plane is a series of services that make Kubernetes work: an API, a database (etcd often) and a bunch of clients using the API. These services often run on Kubernetes itself (often on one or more dedicated machines).

There’s an inception problem: if the services that run the control plane also run in that control plane, how do we start? The answer: with a static manifest.

Useful tools if you want to run your own cluster:

  • Kubeadm: generate static manifests, generating consistent config files, create RBAC objects, create TLS certs, etc.
  • Kine (instead of etcd): etcd is not friendly to SSD lifespan. Kine can also be deployed with Kubeadm.
  • Cilium as the CNI plugin: well documented, less hard to debug, lots of knobs to tweak.
  • Cilium egress gateway: useful for multitenancy.
  • MetalLB: You’ll probably need a load balancer, this is a nice one. Implements failover using Gossip.
  • External-dns: creates A and AAAA records for ingress, load balancer servies and custom resources. But it will not service the DNS records itself.
  • txqueuelen/stateless-dns: combines external-dns with PowerDNS. It makes PowerDNS stateless.

Gitops is what Kubernetes makes it worth it.

Return Of Go Without Wires — Ron Evans

I might be selling him short by summarizing it like this, but Ron showed his adventures with his home made “find my” device, using TinyGo. If you like fiddling around with bluetooth devices, definitely watch the recording.

Related link: https://github.com/hybridgroup/go-haystack

Go Lightning Talks

These are short talks (8 minutes if I recall correctly), and I only took short “check this out later” notes:

Summary / reflections

This section was added on 2025-02-02 after I have had time to reflect on what I’ve heard and seen.

Looking back at yesterday, I must say I liked FOSDEM. I’ve had a great day and was able to listen to a bunch of interesting talks (more on those in a bit). I usually go to these kind of conferences to get inspired and that also did happen yesterday.

And while I’m not really a hallway track kind of person, I did find the atmosphere at the stands pleasant. More than the “normal”, commercial vendor booths you see at most conferences.

Now, about those talks. I think my biggest takeaways are:

  • Using generics in Go is not something to shy away from for performance reasons (at least in most cases). I’ll keep them more in my mind when writing code.
  • Be more aware of garbage collection. While the services I’m working on at work do not have any performance issues (yet), it is good to be aware of some thinks, like reusing slices. Especially for a person rather new to Go (me) it is useful to form good habits.
  • There are lots of ways to tweak your Go binary builds. These are definitely worth investigating and including them in our code base.
  • On a personal note: as the owner of a Raspberry Pi Pico W I’ve learned that I could use TinyGo instead of MicroPython to tinker with it.