January 14

On Ousterhout’s dichotomy – Alex Kladov

For performance, what matters is not so much the code that’s executed, but rather the layout of objects in memory. And the high-level dialect locks-in pointer-heavy GC object model! Even if you write your code in assembly, the performance ceiling will be determined by all those pointers GC needs. To actually get full “low-level” performance, you need to effectively “mirror” the data across the dialects across a quasi-FFI boundary.


January 11

GopherCon UK 2019: Fun with pointers – Daniela Petruzalek

Daniela explains how Go’s pointers are much simpler and safer than those in C/C++, while still providing users the power of indirection. One example surprised me: I was expecting the following snippet to raise a nil pointer dereference error. However, it doesn’t. In the StructGoesBoom method, m = nil only modifies the local copy of the pointer to MyLittleStruct. This means the original struct remains unaffected. Running the code confirms that the struct wasn’t modified at all:

package main

import (
    "fmt"
)

type MyLittleStruct struct {
    something int
}

func (m *MyLittleStruct) StructGoesBoom() {
    fmt.Println("Boom!")

    // This only changes the local copy of pointer m
    m = nil
}

func main() {
    x := MyLittleStruct{1337}
    fmt.Printf("address: %p\n", &x)

    // Desugar x.StructGoesBoom()
    (*MyLittleStruct).StructGoesBoom(&x)
    fmt.Printf("%#v\n", x)
}

Output:

address: 0xc0000140a0
Boom!
main.MyLittleStruct{something:1337}

The “active enum” pattern – Glyph

Glyph shows a neat pattern for encoding behaviors in a Python enum. Instead of defining an enum and then handling behaviors in a function like this:

from enum import Enum, auto


class SomeNumber(Enum):
    one = auto()
    two = auto()
    three = auto()


def behavior(number: SomeNumber) -> int:
    match number:
        case SomeNumber.one:
            print("one!")
            return 1
        case SomeNumber.two:
            print("two!")
            return 2
        case SomeNumber.three:
            print("three!")
            return 3

A better way to do it is:

from dataclasses import dataclass
from enum import Enum
from typing import Callable


@dataclass(frozen=True)
class NumberValue:
    result: int
    effect: Callable[[], None]


class SomeNumber(Enum):
    one = NumberValue(1, lambda: print("one!"))
    two = NumberValue(2, lambda: print("two!"))
    three = NumberValue(3, lambda: print("three!"))

    def behavior(self) -> int:
        self.value.effect()
        return self.value.result

January 10

Be aware of the Makefile effect – William Woodruff

An excellent name for the situation where a tool is so complex to use that people simply copy existing configurations and tweak them until they work for their specific cases.

Tools and systems that enable this pattern often have less-than-ideal diagnostics or debugging support: the user has to run the tool repeatedly, often with long delays, to get back relatively small amounts of information. Think about CI/CD setups, where users diagnose their copy-pasted CI/CD by doing print-style debugging over the network with a layer of intermediating VM orchestration. Ridiculous!


January 09

Ghostty by Mitchell Hashimoto

How do you pronounce Ghostty?

  1. Ghos-tty
  2. Ghost-ty
  3. Something else

Funny name, but an excellent terminal. It’s the first emulator to pull me away from the default macOS/Ubuntu terminal. Since I spend most of my time in VS Code’s integrated terminal, the rough edges of Ghostty don’t bother me much. In fact, I’m quite enjoying it. My config is minimal:

theme = "catppuccin-mocha"
font-family = "JetBrains Mono"
font-size = 20

# Background configuration
background-opacity = 0.95
background-blur-radius = 20

GopherCon 2015: Embrace the interface – Tomas Senart

One great thing about Go is that you can grok a 10-year-old talk and still find it relevant. Here, Tomas demonstrates the decorator pattern in idiomatic Go, showing how to add logging, instrumentation, or retry functionality to an RPC function without polluting its core logic. The result is a Python-like decorator workflow without syntactic sugar that feels native to Go.


January 08

Go developer survey 2024 h2 results

Similar to previous years, the most common use cases for Go were API/RPC services (75%) and command line tools (62%). More experienced Go developers reported building a wider variety of applications in Go. This trend was consistent across every category of app or service. We did not find any notable differences in what respondents are building based on their organization size. Respondents from the random VS Code and GoLand samples did not display significant differences either.

What respondents build with Go


January 07

How I program with LLMs – David Crawshaw

My LLM workflow is pretty similar to David’s. Instead of dumping my whole codebase into the model, I find it way more effective to use the chat UI and tackle a problem piece by piece. The responses are way better when the problem space is smaller and the model needs less out-of-band information to work—probably how a human would perform in a similar context.

The reservoir sampler for the quartiles of floats example is a perfect demonstration of why LLMs are so useful in programming, even with their tendency to make things up or get stuck in a rut.


January 06

GopherCon 2020: Go is boring… and that’s fantastic - Jonathan Bodner

When you have a struct in Go that contains other structs, all the data is stored sequentially in memory. This is different from classes in all those other languages, where each field in a class is actually a pointer to some other memory, which means your memory access in those languages is effectively random (random memory access is slower than sequential access).


January 05

Back to basics: why we chose long polling over WebSockets – Nadeesha Cabral

Long polling has its fair share of issues, but in my experience, it’s been more reliable than WebSockets in most cases where I’ve needed to maintain long-running HTTP connections. Modern databases can handle a surprising number of connections these days, and adding proper indexes can mitigate the risk of overwhelming the database with too many open connections.

Sure, Server-Sent Events (SSE) and WebSockets exist, but reliably detecting changes in the backend and delivering them to the right client still feels like an unsolved problem. Until that’s resolved, long polling remains a surprisingly simple and robust solution that just works. It’s already used as the fallback solution in most WebSocket setups.


January 04

Kids can’t use computers… and this is why it should worry you – Marc Scott

Damn, the anecdotes just keep getting better and better.

A sixth-former brings me his laptop, explaining that it is running very slowly and keeps shutting down. The laptop is literally screaming, the processor fans running at full whack and the case is uncomfortably hot to touch. I run Task Manager to see that the CPU is running at 100% despite the only application open being uTorrent (which incidentally had about 200 torrent files actively seeding). I look at what processes are running and there are a lot of them, hogging the CPU and RAM. What’s more I can’t terminate a single one. ‘What anti-virus are you using?’ I ask, only to be told that he didn’t like using anti-virus because he’d heard it slowed his computer down. I hand back the laptop and tell him that it’s infected. He asks what he needs to do, and I suggest he reinstalls Windows. He looks at me blankly. He can’t use a computer.

A kid puts her hand up in my lesson. ‘My computer won’t switch on,’ she says, with the air of desperation that implies she’s tried every conceivable way of making the thing work. I reach forward and switch on the monitor, and the screen flickers to life, displaying the Windows login screen. She can’t use a computer.

A teacher brings me her school laptop. ‘Bloody thing won’t connect to the internet.’ she says angrily, as if it were my fault. ‘I had tonnes of work to do last night, but I couldn’t get on-line at all. My husband even tried and he couldn’t figure it out and he’s excellent with computers.’ I take the offending laptop from out of her hands, toggle the wireless switch that resides on the side, and hand it back to her. Neither her nor her husband can use computers.


January 03

Be a property owner and not a renter on the internet – Den Delimarsky

I’m loving this renaissance of personal blogs. Den’s take on POSSE (Publish Own Site, Syndicate Elsewhere) really resonates—it’s the only viable way to create content without getting trapped in the walled gardens of billion-dollar megacorps. About five years ago, Medium burned me, so I followed Simon Willison’s advice and started this blog. Easily one of the best decisions I’ve made in the past decade.

I would recommend avoiding any places where there is content lock-in. You want to optimize for future portability. That is, if you can’t easily export your full content history (e.g., blog posts) and move them somewhere else, don’t use that service. If your content is locked into a service, and at some point that service decides that you are no longer a wanted customer, all that effort you put into making it available to your customers can vanish on a moment’s notice. Prefer sites that allow you to publish in open formats, such as Ghost.

Minifeed

Minifeed is a delightful blog aggregator I discovered today. It’s full of blogs I’d never heard of and uses a smart, vector-driven approach to group similar posts.

minifeed

Modern for Hacker News

I spend an absurd amount of time browsing Hacker News and just stumbled upon this gem. On iOS, Hack is my go-to app for exploring the orange site, but on desktop, I’ve mostly stuck with the original UI. Enter Modern—a Chrome extension that transforms the brutalist interface into something sleek, like this:

modern


January 02

Stop designing languages. Write libraries instead – Patrick S. Li

When I first started dabbling with Go, I couldn’t help but wonder why it didn’t have anything as slick as Python’s FastAPI. Generating API docs directly from code required a flexible type system and robust introspection capabilities, which Go just didn’t have back then. But now, with generics in the mix, libraries are finally emerging that can generate OpenAPI specs and docs from code without much fuss.

The design of the programming language directly determines what sort of libraries you can write and how easy they are to use in the end. In the C language, the only major feature provided for enabling reuse is the ability to declare and call functions. So guess what? The majority of C libraries are basically large collections of functions. Ruby on Rails provides a concise way for expressing: do this when the button is clicked. The “do this” part is implemented in Ruby as a first-class function. How would it be implemented in languages like Java which don’t support them? Well, the behaviour of first-class functions can be mocked by defining a new event handler class with a single perform_action method and then passing an instance of this class to the button object. So guess what? Using a Java library typically entails declaring a humongous number of handler classes. The programming language directly shapes the design of its libraries.


January 01

Databases in 2024: A year in review – Andy Pavlo

From Redis and Elasticsearch’s licensing drama to Databricks vs. Snowflake’s billion-dollar sparring, to DuckDB’s integration into Postgres—this post offers a great overview of the major database events of 2024.

I’ve been reading Andy’s database event reviews for the past three years and love his work. However, I’m not sure how to feel about the unwarranted shade thrown at Redis. While I don’t agree with Redis Ltd.’s licensing decisions, I still think it’s a marvelous engineering artifact that has shaped the query languages of many similar key-value storage systems.