Beyond Paradigms • The Applied Go Weekly Newsletter 2024-10-06
Your weekly source of Go news, tips, and projects
Did you ever try mentioning to functional programming purists that Go has some aspects of functional programming (specifically, functions as first-class citizens)? How did they react? Chances are that they immediately listed a ton of reasons why Go cannot be functional in any regard. It's just one of these lesser, procedural languages.
Ok, fine. But Go still has first-class functions. The problem here is that this feature touches a programming paradigm that Go actually doesn't subscribe to. So mentioning that Go has aspects of functional programming can trigger wrong associations, because we humans love categorizations even if they don't fit well.
I continue the rant in the Spotlight section, but first, let's look into distributed transactions, old code that runs unchanged, synchronization primitives, static analysis for templates, and torches being handed over.
Featured articles
Distributed Transactions in Go: Read Before You Try | Three Dots Labs blog
When designing distributed data processing, using distributed transactions should be your last resort. They add complexity and are most likely overkill. Miłosz Smółka introduces you to two patterns that can help you stay clear of distributed transactions as long as possible: Eventual consistency and the outbox pattern.
Glad I did it in Go
How often does it happen that you come back to code you've written eight years ago and you think to yourself, "Glad I did it in Go"? Or would you be more like, "Darn! If only I had written it in Go!"
Concurrency Control in Go: Inside rqlite’s Custom Synchronization Primitives – Vallified
Writing a distributed database implies intense use of concurrency. Philip O'Toole, creator of rqulite
, a distributed database based on SQLite, encountered several limitations of Go's built-in concurrency tooling and built a few custom concurrency primitives.
Go 1.23.2 and Go 1.22.8 are released
Download binary and source distributions from the Go website, view the release notes, or dig into the completed issues.
Podcast corner
Toying with static analysis of HTML templates
After having talked to Templ maintainers in the previous episode, Dominic St-Pierre works on a static analysis tool for templates to catch errors like typos in a field name.
Russ Cox on passing the torch
Do you remember the news about Russ Cox stepping back from his role as Go tech lead? (The diligent Applied Go Weekly Newsletter team (i.e., me) reported this in the 2024-08-04 issue.) Russ announced that Austin Clements would take over the role on September 1st, and Cherry Mui steps into Austin's previous role as Go core tech lead.
In this Go Time episode, Russ, Austin, and Cherry talk to Angelica about the decisions behind the change and what this change brings for the future.
More importantly, you'll learn something about Matcha tea powder quality.
Spotlight: Go is...?
A few days ago, I posted an attempt at explaining Go on social media. The post was inspired by a question I got in a Reddit thread: "Go is neither an OOP language nor an FP language. What is it, then?" I answered that Go is kind of "OOP minus inheritance, with a bit of functional programming."
Object-oriented, functional, procedural: paradigms galore!
It's human nature to put everything into categories, into mental compartments of varying granularity. The world is easier to grok this way. Friend and foe, male and female, black and white, us and them. But the world doesn't work this way. There is always a spectrum between two categories, and beyond.
And so, the IT world invented tags to slap on programming languages. Procedural, object-oriented, functional, imperative, and whatnot. Surely, these tags (known as "programming paradigms") help clarify the mental concept behind a language design and the programming style the language supports best.
Paradigms are only a crutch
The problems with this approach start with the very definitions of these paradigms. When is a language object-oriented? When is it functional? Ironically, the language LISP, widely considered a functional programming language (since it originates from a mathematical approach to programming, influenced by lambda calculus), is the first language associated with object-oriented programming. Defining object-oriented languages as "having inheritance" is a popular myth. By the most minimalist definition of object orientation, an object-oriented language only needs to support abstract data types—objects that have an internal states and methods that query or change that state. Another definition that gained some popularity was coined by Alan Kay. Asked about his understanding of object orientation, his answer was:
"OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.
The functional programming paradigm is also fraught with ambiguities. For Functional Programming purists, a functional language is truly functional if it supports only pure functions with no side effects whatsoever. With this definition, LISP is not a pure functional language.
Multi-paradigm languages?
In fact, Wikipedia designates both Go and LISP as "multi-paradigm languages". Go is characterized as concurrent, imperative, functional, object-oriented, and LISP carries the tags functional, procedural, reflective, meta.
Wait a minute—Go as a functional language? News to me.
Sure, Go's functions are first-class citizens. You can assign them to variables or pass them to, or return them from, functions. Functions can even have methods. But this single aspect doesn't make Go functional. And Wikipedia isn't even in agreement with itself about the paradigms Go covers. The page Comparison of multi-paradigm programming languages lists Go explicitly as neither functional nor object-oriented.
And what's a "programming paradigm" anyway? Look around at that Wikipedia page. There is "functional", "procedural", and "object-oriented", but also "pipeline" (which I would consider syntactic sugar), "distributed" (an architectural concept, rather than a language design concept), or "visual" (a fancy, interactive user interface on top of a procedural, dataflow, or other kind of language).
Moreover, Go and Rust may share the same paradigms, but their approach to memory management—automatic versus manual (compiler-guided)—is perhaps the biggest distinguishing feature between the two languages. And this is not even listed as a paradigm.
Programming paradigms are obviously not an optimal way of categorizing languages.
Programming languages are like spices
Curry powder, Garam Masala, Ras el Hanout, Café de Paris—all these are blends of various spices. The particular combination of individual herbs and spices gives these blends their unique taste.
Programming languages are no different. By combining aspects from various programming paradigms, language designers create a unique programming experience.
Shouldn't we better talk about a programming language like a spice blend, rather than a paradigm mishmash? Features instead of coarse-grained categorizations. If nothing else, at least it provides fewer incentives for language advocacy.
Quote of the Week: A rare intersection
Go is at a rare intersection of simplicity, performance, maintainability and simple concurrency primitives. It is extremely practical if you don't focus in "but Go does not have this feature I like from other language I have been using for the last 10 years".
It has its missing parts but it's extremely practical for many use cases.
More articles, videos, talks
Building with Go in a monorepo using Bazel, Gazelle and bzlmod
Every company grows their own, specific toolset for software development. Tools, however, tend to have quirks, especially in combination with other tools, and after the author spent 6 hours breaking his head to get a Bazel monorepo setup working locally, he decided to do a writeup to help others avoid the footslings.
Writing raw SQL easier with pgx and sqlc in Go
If you want control over your database queries, use a SQL-first approach. And if you use PostgreSQL exclusively, why not combining two SQL-with-Go powerhouses for maximum effect: sqlc
, the SQL code generator, and pgx
, an alternative PostgreSQL driver and toolkit.
Some Go web dev notes
Julia Evans, of Wizard Zines fame, summarizes her experiences with programming a website in Go.
Distributed metrics in PHP using Go and Gob
Uh, why would someone working in the PHP realm choose Go for collecting metrics? And why would someone then pick Gob, a binary protocol that was strictly designed for "communicating between servers written in Go"?
Easy: Gob is a highly efficient data protocol that uses an order of magnitude less space than Prometheus metrics for the same data. And, according to the author, it is much easier to use.
Joining errors in Go – tpaschalis – software, systems
A function can join multiple errors into one, but there's a catch that the callers who try to unwrap that error may stumble upon.
Probabilistic Early Expiration in Go | Dizzy zone
Refreshing cache entries with a certain probability before they expire spreads the refresh activity across the timeline and helps prevent cache stampedes.
High-Resolution Timers on Windows | Microsoft for Go Developers
Go 1.23 supports timers at a resolution of about 0.5ms, a 30-fold improvement over the previous limit of about 15ms.
Inside Go's Unique Package: String Interning Simplified
Articles about the unique
package aren't quite unique anymore. (Sorry, I was searching for Yet Another Silly Pun™ on the package name.) But this article is unique (sorry again) by being a follow-up to an article from a year ago that describes string interning as a performance optimization technique for databases and demonstrates how to implement it using a map.
Avoid inaccurate tests: Use httptest when testing HTTP handlers in Go/Golang
Testing HTTP endpoints is more involved than unit-testing "pure" functions. To facilitate testing, Go comes with the httptest
package. Willem Shots explains its usage.
Map with Expiration in Go
Do you need Redis? Do you really need Redis in this project? Maybe you just need a simple in-memory map with expiring items. You don't need much more than a screenful of code.
Projects
Libraries
modernc.org/tk9.0
It's well been two decades ago when I tinkered with Tcl/Tk, a scripting language/GUI toolkit combo. Now, Tk, the GUI part, is back as a Go module! Tk is certainly a great option for building ad-hoc GUIs for CLI apps, especially as no CGO is attached.
GitHub - francescoalemanno/cryptipass: CryptiPass is a Go library for generating secure high-entropy, pronounceable passphrases.
This package does not generate passphrases from a large dictionary but rather through a Markov chain algorithm. The resulting passphrase is still pronounceable but not made of dictionary words, for example: jesside.flyperm.aunsis.dertsy
.
GitHub - codesoap/lineworker: A worker pool which processes work in parallel but outputs results in the order the work was given
So you throw bags of work at your pool of tireless workers, but the results aren't in the correct order? lineworker
ensures that results are passed back in the order the work was given
Tools and applications
GitHub - emad-elsaid/xlog: 💥 Personal knowledge management application. One binary HTTP server. works in any Markdown directory. autolinks pages, hashtags, auto preview images link, screenshare, screenshot, camera recording and audio recording embedded in the note. and fast search through the KB
Whether you want to start a personal Wiki or bring a tree of Markdown files online, Xlog is one of the easiest ways to get started. Drop Xlog into a directory full of Markdown files, and it "just works". Edit files online, and get auto-linking to other pages by simply writing the page name. If you're missing any feature, you can write your own extensions.
GitHub - rrgmc/whymodwhy: whymodwhy discovers what packages from the root go.mod file should be upgraded in order to upgrade the passed package name
You could do a go get -u
followed by git diff go.mod
(HT to /u/chocoreader), but whymodwhy
adds some convenience to the task.
GitHub - TwoBitCoders/jx: jx: Memory-Safe JSON Processing using JavaScript implemented in Go
jx
is similar to the popular jq
but uses JavaScript instead of a domain-specific language for writing transformations.
GitHub - pijng/prep: Golang comptime. Pure blasphemy
Compile-time function evaluation is evil cool something that Zig has now available for Go.
GitHub - DanielLiu1123/gencoder: A code generator that keeps your changes during regeneration, powered by Handlebars.
Simple code generators overwrite any manual change applied to the generated code. gencoder
detects and preserves manual changes.
GitHub - pratikdaigavane/trading-leaderboard: Efficient and scalable program that dynamically updates the leader-board with the latest ranking every minute, ensuring accuracy and performance even under high trading activity.
How to build a dynamic leader board with quite a few rules and assumptions attached? Here is on possible way.
GitHub - x-sushant-x/Rate-Shield: A completely configurable rate limiter that can apply rate limiting on individual APIs with individual rules.
Limiting the rate of incoming requests can reduce system load and prevent API abuse. This rate limiter allows you to apply individual rules to each API separately and comes with a nice webUI dashboard.
GitHub - charmbracelet/bubbletea: A powerful little TUI framework 🏗
Install werkzeugkasten
(German for toolbox) once inside a container and have 111 CLI tools (and counting) on your fingertips.
Completely unrelated to Go
Software development topics I've changed my mind on after 6 years in the industry
Think back to the beginning of your career in software development: What beliefs did you have back then that you dropped, and what new beliefs and opinions did you pick up? Chris Kiel found quite a few.
Discovering direnv
There are few tools that do a seemingly simple job in the background, but they do it so well that they become indispensible to many. direnv
is such a tool.
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