> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Golang 1.24 is looking seriously awesome

export const PostMeta = ({data = {}}) => {
  const {author, date, image} = data;
  const authors = Array.isArray(author) ? author : author ? [author] : [];
  const resolveAuthor = slug => {
    const entry = AUTHOR_MAP[slug] || ({});
    const name = entry.name || slug;
    const github = entry.github || null;
    const linkedin = entry.linkedin || null;
    const url = github ? `https://github.com/${github}` : linkedin || null;
    const avatarUrl = github ? `https://github.com/${github}.png?size=64` : null;
    return {
      name,
      url,
      avatarUrl
    };
  };
  const formattedDate = date ? new Date(date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }) : null;
  if (!image && authors.length === 0 && !formattedDate) return null;
  const AUTHOR_MAP = {
    "aaron-collier": {
      "name": "Aaron Collier"
    },
    "aaron-dudenhofer": {
      "name": "Aaron Dudenhofer"
    },
    "aaron-porter": {
      "name": "Aaron Porter"
    },
    "adriaan-odendaal": {
      "name": "Adriaan Odendaal"
    },
    "ajmal": {
      "name": "Ajmal Siddiqui"
    },
    "akalipetis": {
      "name": "Antonis Kalipetis"
    },
    "alexander-varwijk": {
      "name": "Alexander Varwijk"
    },
    "alicia-bevilacqua": {
      "name": "Alicia Bevilacqua"
    },
    "amelie-deguerry": {
      "name": "Amelie Deguerry"
    },
    "anacidre": {
      "name": "Ana Cidre",
      "linkedin": "https://www.linkedin.com/in/ana-cidre"
    },
    "andoni": {
      "name": "Andoni Auzmendi"
    },
    "andrei-taranu": {
      "name": "Andrei (Alex) Taranu",
      "linkedin": "https://www.linkedin.com/in/andrei-alex-taranu/"
    },
    "andrew-baxter": {
      "name": "Andrew Baxter"
    },
    "andrew-melck": {
      "name": "Andrew Melck"
    },
    "antoine-crochet-damais": {
      "name": "Antoine Crochet Damais"
    },
    "augustin-delaporte": {
      "name": "Augustin Delaporte",
      "linkedin": "https://www.linkedin.com/in/augustindelaporte/"
    },
    "branislav-bujisic": {
      "name": "Branislav Bujisic"
    },
    "carl-smith": {
      "name": "Carl Smith"
    },
    "caroline-leroy": {
      "name": "Caroline Leroy"
    },
    "cati-mayer": {
      "name": "Cati Mayer"
    },
    "catplat": {
      "name": "C Trinkwon"
    },
    "ceelolulu": {
      "name": "Celeste van der Watt"
    },
    "chadwcarlson": {
      "name": "Chad Carlson",
      "github": "chadwcarlson",
      "linkedin": "https://www.linkedin.com/in/chadwcarlson"
    },
    "chris-ward": {
      "name": "Chris Ward"
    },
    "chris-yates": {
      "name": "Chris Yates"
    },
    "christian-sieber": {
      "name": "Christian Sieber"
    },
    "christopher-lockheardt": {
      "name": "Christopher Lockheardt"
    },
    "christopher-skene": {
      "name": "Christopher Skene"
    },
    "chuck-morgan": {
      "name": "Chuck Morgan"
    },
    "corey-dockendorf": {
      "name": "Corey Dockendorf"
    },
    "crell": {
      "name": "Crell"
    },
    "damz": {
      "name": "Damz"
    },
    "dan-morrison": {
      "name": "Dan Morrison"
    },
    "davidbonachera": {
      "name": "David Bonachera",
      "github": "davidbonachera",
      "linkedin": "https://www.linkedin.com/in/davidbonachera"
    },
    "dereliahmet1": {
      "name": "Ahmet Faruk Dereli"
    },
    "devicezero": {
      "name": "Jonas Kröger",
      "github": "devicezero",
      "linkedin": "https://www.linkedin.com/in/jonaskroeger/"
    },
    "doug-goldberg": {
      "name": "Doug Goldberg"
    },
    "duncan-naves": {
      "name": "Duncan Naves",
      "github": "duncannaves",
      "linkedin": "https://www.linkedin.com/in/duncan-naves-a94423aa"
    },
    "erika-bustamante": {
      "name": "Erika Bustamante"
    },
    "fabpot": {
      "name": "Fabien Potencier"
    },
    "flovntp": {
      "name": "Florent Huck",
      "github": "flovntp",
      "linkedin": "https://www.linkedin.com/in/florenthuck"
    },
    "fred-plais": {
      "name": "Fred Plais"
    },
    "gauthier-garnier": {
      "name": "Gauthier Garnier"
    },
    "gilzow": {
      "name": "Paul Gilzow"
    },
    "gmoigneu": {
      "name": "Guillaume Moigneu",
      "github": "gmoigneu",
      "linkedin": "https://www.linkedin.com/in/guillaumemoigneu/"
    },
    "gregqualls": {
      "name": "Greg Qualls"
    },
    "guguss": {
      "name": "Augustin Delaporte"
    },
    "haylee-millar": {
      "name": "Haylee Millar"
    },
    "ivana-kotur": {
      "name": "Ivana Kotur"
    },
    "jackrabbithanna": {
      "name": "Mark Hanna"
    },
    "jared-wright": {
      "name": "Jared Wright",
      "github": "jww-sh",
      "linkedin": "https://www.linkedin.com/in/jaredwaynewright"
    },
    "jessica-orozco": {
      "name": "Jessica Orozco"
    },
    "joey-stanford": {
      "name": "Joey Stanford"
    },
    "john-grubb": {
      "name": "John Grubb"
    },
    "jonas-kruger": {
      "name": "Jonas Kruger"
    },
    "kathryn-frazer": {
      "name": "Kathryn Frazer"
    },
    "kemiojo": {
      "name": "Kemi Elizabeth Ojogbede"
    },
    "kieronsambrook-smith": {
      "name": "Kieronsambrook Smith"
    },
    "laurent-arnoud": {
      "name": "Laurent Arnoud",
      "linkedin": "https://www.linkedin.com/in/laurent-arnoud-861b44121/"
    },
    "letoya-boyne": {
      "name": "Letoya Boyne"
    },
    "lolautruche": {
      "name": "Jérôme Vieilledent"
    },
    "lyly-lepinay": {
      "name": "Lyly Lepinay"
    },
    "manauwar-alam": {
      "name": "Manauwar Alam"
    },
    "marc-antoine-porri": {
      "name": "Marc Antoine Porri"
    },
    "maria-antinkaapo": {
      "name": "Maria Antinkaapo"
    },
    "maria-de-anton": {
      "name": "Maria De Anton"
    },
    "mark-dorison": {
      "name": "Mark Dorison"
    },
    "markus-hausammann": {
      "name": "Markus Hausammann"
    },
    "mary-thomas": {
      "name": "Mary Thomas"
    },
    "mathias-bolt-lesniak": {
      "name": "Mathias Bolt Lesniak"
    },
    "mathieu-strauch": {
      "name": "Mathieu Strauch"
    },
    "matthias-van-woensel": {
      "name": "Matthias Van Woensel",
      "linkedin": "https://www.linkedin.com/in/matthias-van-woensel-267a069"
    },
    "michael-sharp": {
      "name": "Michael Sharp"
    },
    "mupsi": {
      "name": "Marine Gandy"
    },
    "natalie-harper": {
      "name": "Natalie Harper"
    },
    "ngommenginger": {
      "name": "Nicolas Gommenginger",
      "linkedin": "https://www.linkedin.com/in/nicolas-gommenginger"
    },
    "nicholas-bennison": {
      "name": "Nicholas Bennison"
    },
    "nicholas-vahalik": {
      "name": "Nicholas Vahalik"
    },
    "nick-hardiman": {
      "name": "Nick Hardiman"
    },
    "nickanderegg": {
      "name": "Nickanderegg"
    },
    "nicolas-grekas": {
      "name": "Nicolas Grekas",
      "github": "nicolas-grekas",
      "linkedin": "https://www.linkedin.com/in/nicolasgrekas/"
    },
    "niti-malwade": {
      "name": "Niti Malwade"
    },
    "opensocialteam": {
      "name": "Opensocialteam"
    },
    "ori-pekelman": {
      "name": "Ori Pekelman"
    },
    "otavio-santana": {
      "name": "Otavio Santana"
    },
    "palwandi": {
      "name": "Pawan Alwandi",
      "github": "pawpy",
      "linkedin": "https://www.linkedin.com/in/pawanalwandi"
    },
    "patrick-boest": {
      "name": "Patrick Boest"
    },
    "patrick-dawkins": {
      "name": "Patrick Dawkins",
      "github": "pjcdawkins",
      "linkedin": "https://www.linkedin.com/in/patrickdawkins"
    },
    "patrick-klima": {
      "name": "Patrick Klima"
    },
    "pjcdawkins": {
      "name": "Pjcdawkins"
    },
    "prineet-kaurbhurji": {
      "name": "Prineet Kaurbhurji"
    },
    "quentin-sinig": {
      "name": "Quentin Sinig"
    },
    "ralt": {
      "name": "Florian Margaine",
      "github": "ralt",
      "linkedin": "https://www.linkedin.com/in/florian-margaine-43971136"
    },
    "ramanathanramakrishnamurthy": {
      "name": "Ramanathanramakrishnamurthy"
    },
    "remi-lejeune": {
      "name": "Rémi Lejeune"
    },
    "ribel": {
      "name": "Taras Kruts"
    },
    "robert-douglass": {
      "name": "Robert Douglass"
    },
    "rudy-weber": {
      "name": "Rudy Weber"
    },
    "ryan-hicks": {
      "name": "Ryan Hicks"
    },
    "sabri-helal": {
      "name": "Sabri Helal"
    },
    "savannah-bergeron": {
      "name": "Savannah Bergeron"
    },
    "shannon-vettes": {
      "name": "Shannon Vettes"
    },
    "shawn-ogasawara": {
      "name": "Shawn Ogasawara",
      "linkedin": "https://www.linkedin.com/in/shawn-ogasawara-83a9a0/"
    },
    "shawna-spoor": {
      "name": "Shawna Spoor"
    },
    "shedrack-akintayo": {
      "name": "Shedrack Akintayo"
    },
    "simon-ruggier": {
      "name": "Simon Ruggier"
    },
    "sophie-van-der-kindere": {
      "name": "Sophie Van Der Kindere"
    },
    "stefanos-thampis": {
      "name": "Stefanos Thampis"
    },
    "stephen-weinberg": {
      "name": "Stephen Weinberg"
    },
    "sukhman-virk": {
      "name": "Sukhman Virk"
    },
    "sumaira-nazir": {
      "name": "Sumaira Nazir"
    },
    "sumer": {
      "name": "Sümer Cip"
    },
    "syed-raza": {
      "name": "Syed Raza"
    },
    "tamara-bacchia": {
      "name": "Tamara Bacchia"
    },
    "tara-arnold": {
      "name": "Tara Arnold"
    },
    "theosakamg": {
      "name": "Mickael Gaillard",
      "github": "theosakamg"
    },
    "thomasdiluccio": {
      "name": "Thomas di Luccio"
    },
    "tim-anderson": {
      "name": "Tim Anderson"
    },
    "tom-helmer-hansen": {
      "name": "Tom Helmer Hansen"
    },
    "tylermills": {
      "name": "Tyler Mills"
    },
    "upsun": {
      "name": "Upsun"
    },
    "veronika-tolkachova": {
      "name": "Veronika Tolkachova",
      "linkedin": "https://www.linkedin.com/in/veronika-tolkachova-169167a2"
    },
    "vince-parker": {
      "name": "Vince Parker"
    },
    "vinnie-russo": {
      "name": "Vincenzo Russo"
    },
    "vrobert78": {
      "name": "Vincent Robert",
      "github": "vrobert78",
      "linkedin": "https://www.linkedin.com/in/vincent-robert-498a883"
    },
    "yuriy-babenko": {
      "name": "Yuriy Babenko"
    },
    "yuriy-gerasimov": {
      "name": "Yuriy Gerasimov"
    }
  };
  return <div className="post-meta">
      {(authors.length > 0 || formattedDate) && <div className="post-meta-info">
          {authors.length > 0 && <div className="post-meta-authors">
              {authors.map(slug => {
    const {name, url, avatarUrl} = resolveAuthor(slug);
    const inner = <>
                    {avatarUrl && <img src={avatarUrl} alt={name} className="post-meta-avatar" />}
                    <span className="post-meta-author-name">{name}</span>
                  </>;
    return url ? <a key={slug} href={url} target="_blank" rel="noopener noreferrer" className="post-meta-author">
                    {inner}
                  </a> : <span key={slug} className="post-meta-author">{inner}</span>;
  })}
            </div>}
          {authors.length > 0 && formattedDate && <span className="post-meta-separator" aria-hidden="true">·</span>}
          {formattedDate && <span className="post-meta-date">{formattedDate}</span>}
        </div>}
      {image && <img src={image} alt="" className="post-meta-image" aria-hidden="true" />}
    </div>;
};

<PostMeta data={{ author: ["damz"], date: "2024-12-15T15:56:29-05:00", image: "/images/posts/discussions/go-124/gopher.webp" }} />

The Golang team just released the [first release candidate of Golang 1.24](https://tip.golang.org/doc/go1.24). At Upsun, we use Golang extensively for everything in our hot path, especially for the routing of HTTP requests throughout our infrastructure. Here is what we are looking forward to the most.

### Some nice performance improvements

We have not looked into these very closely yet, but they seem nice:

* 2-3% performance improvement across the board, driven by "a new builtin map implementation based on Swiss Tables, more efficient memory allocation of small objects, and a new runtime-internal mutex implementation"[^1]; and
* Two new cgo directives (`noescape` and `nocallback`)[^2] that have the potential to reduce the overhead of calling C code from Go in some cases

[^1]: *Runtime*, [Go 1.24 Release Notes](https://tip.golang.org/doc/go1.24#runtime).

[^2]: *Tools, Cgo*; [Go 1.24 Release Notes](https://tip.golang.org/doc/go1.24#cgo).

### A weak pointer implementation (finally!)

Probably my favorite, Go 1.24 includes an implementation of a weak pointer.

A weak pointer is a reference to an object that does not prevent the garbage collector from collecting it. In practice, the implementation is simply a `weak.Pointer[T]` (which nicely mirrors `atomic.Pointer[T]`), which has a `Value() *T` method.

This new weak pointer concept -- in addition to the `unique` package [introduced in Go 1.23](https://go.dev/blog/unique) -- has the potential of powering nice improvement of memory usage in real-world Go applications.

### Post-quantum cryptography

This release introduces support for post-quantum cryptography in the `crypto/tls` package. The standard library now includes ML-KEM, "a post-quantum key exchange mechanism formerly known as Kyber and specified in [FIPS 203](https://doi.org/10.6028/NIST.FIPS.203)" [^3].

Post-quantum cryptography, if you haven't been following, is a reference to a new set of cryptographic algorithms that are deemed resistant to attacks by quantum computers, which could potentially break many of the current commonly used cryptographic algorithms.

[^3]: *New crypto/mlkem package*; [Go 1.24 Release Notes](https://tip.golang.org/doc/go1.24#crypto-mlkem).

### Encrypted Client Hello (ECH) in `crypto/tls`

The goal of Encrypted Client Hello (ECH), and of its predecessor Encrypted SNI (ESNI) is to bring a long standing privacy gap in TLS: while the actual communication over TLS is private, the identity of the server isn't. The protocol uses a public key, distributed via DNS and obtained using DNS-over-HTTPS, for encryption during the client's first flight.

This is an option we are going to look into offering on Platform.sh and Upsun at one point. We still need to figure out how to best do that.

### `encoding/json` gets better support for zero value through the new `omitzero` tag

This release fixes a long-standing issue in `encoding/json`: the `omitempty` tag only supports a subset of types, and has a definition that is at odd with the standard definition of the zero value in the language. The new `omitzero` tag now allows you to specify that a field should be omitted from the serialization if it has the zero value for its type.

The current `omitempty` option specifies that the field should be omitted from the encoding *"if the field has an empty value, defined as `false`, `0`, a `nil` pointer, a `nil` interface value, and any empty array, slice, map, or string"*. This has always been unfortunate, because Golang has different definition of what a ["zero value"](https://go.dev/ref/spec#The_zero_value) is: *"`false` for booleans, `0` for numeric types, `""` for strings, and `nil` for pointers, functions, interfaces, slices, channels, and maps"*.

If you compare the two definitions, you would note they are identical for booleans, all numeric types, empty arrays and interface values. But they handle slices and maps differently:

* `omitempty` will omit any empty slices or maps (i.e. slices or maps that satisfy `len(S) == 0`), which includes slices or maps that are `nil`
* `omitzero` on the other hand will only omit slices or maps that are `nil`

They also handle non-pointer struct values differently. Take [this example](https://go.dev/play/p/UWVF3QAlAS0?v=gotip):

```golang {fileName="omitzero-example.go"} theme={null}
package main

import (
	"encoding/json"
	"log"
)

type Foo struct {
	OmitEmpty Bar `json:"omitempty,omitempty"`
	OmitZero  Bar `json:"omitzero,omitzero"`
}

type Bar struct {
	A int `json:"a"`
}

func main() {
	data, _ := json.Marshal(&Foo{})
	log.Printf("Generates: %s", string(data))
}
```

It generates:

```json theme={null}
{"omitempty": {"a": 0}}
```

Given the above, our recommendation would be to continue using `omitempty` for maps and slices, but use `omitzero` for everything else.

### A new `tool` directive in `go.mod`

This release adds a new `tool` directive to `go.mod`, allowing you to specify dependencies to build tools without having to resort to the current convention of having an empty `tools.go` somewhere in your project.

Previously, a project depending on the `stringer` tool to generate string versions of enums would have somewhere a file containing something like:

```golang theme={null}
//go:build ignore

package foo

import (
	_ "golang.org/x/tools/cmd/stringer"
)
```

And you would execute that tool with a `go:generate` line like this:

```
//go:generate go run golang.org/x/tools/cmd/stringer -type Foo
```

It worked well enough. But now in Golang 1.24, you can simply add a `tool` directive to your `go.mod`, like this:

```
tool golang.org/x/tools/cmd/stringer
```

This tool becomes available by just running:

```
//go:generate go tool stringer -type Foo
```

Not a huge deal, but still a nice quality of life improvement.

### Context support in the `testing` package

I have been wanting this for a while. The `*testing.T` and `*testing.B` types now have a `Context() context.Context` method, returning a context that is canceled just before `Cleanup` functions are called.

This will allow replacing:

```golang theme={null}
func TestFoo(t *testing.T) {
    ctx, cancelFn := context.WithCancel(context.Background())
    t.Cleanup(cancelFn)

    // [...]
}
```

with:

```golang theme={null}
func TestFoo(t *testing.T) {
    ctx := t.Context()

    // [...]
}
```

Another nice quality of life improvement, and the potential to make it easier and more natural to build cleaner tests.

### A new `testing/synctest` package for testing concurrent code

This is still experimental, but looks really fun. It is a new package that allows you to define "bubbles" of goroutines into which a fake clock is provided (i.e. `time.Now()` returns something different). This will eventually make it easier to test time-sensitive concurrent code, where the best practice right now is to provide a clock function returning the current time (i.e. a `func() time.Time`), so that fake time can be injected during tests (it is, for example, how the `github.com/juju/ratelimit` token-bucket implementation [is tested](https://github.com/juju/ratelimit/blob/v1.0.2/ratelimit.go#L45)).

### A lot of other things

The Golang team really gave us a nice present this holiday season. There is so much more to mention:

* An improved finalizer support with `runtime.AddCleanup`;
* The new `encoding.TextAppender` and `encoding.BinaryAppender` interfaces, and their support on many types throughout the standard library;
* Cryptographically secure random text strings with the new `rand.Text` function;
* ... and so much more.

Read the [full draft release notes](https://tip.golang.org/doc/go1.24), and don't hesitate to come and discuss your favorite parts with us [on Discord](/)!
