From 464a2af6db68d1aec59fb70f4f84ad8b667a62ea Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Fri, 20 Dec 2024 15:19:10 -0600 Subject: [PATCH] Add Produce The Zero Value Of A Generic Type as a Go TIL --- README.md | 3 +- ...roduce-the-zero-value-of-a-generic-type.md | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 go/produce-the-zero-value-of-a-generic-type.md diff --git a/README.md b/README.md index da725b1..f33a8e4 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186). -_1543 TILs and counting..._ +_1544 TILs and counting..._ --- @@ -412,6 +412,7 @@ _1543 TILs and counting..._ - [Not So Random](go/not-so-random.md) - [Parse A String Into Individual Fields](go/parse-a-string-into-individual-fields.md) - [Parse Flags From CLI Arguments](go/parse-flags-from-cli-arguments.md) +- [Produce The Zero Value Of A Generic Type](go/produce-the-zero-value-of-a-generic-type.md) - [Redirect File To Stdin During Delve Debug](go/redirect-file-to-stdin-during-delve-debug.md) - [Replace The Current Process With An External Command](go/replace-the-current-process-with-an-external-command.md) - [Sleep For A Duration](go/sleep-for-a-duration.md) diff --git a/go/produce-the-zero-value-of-a-generic-type.md b/go/produce-the-zero-value-of-a-generic-type.md new file mode 100644 index 0000000..ea96388 --- /dev/null +++ b/go/produce-the-zero-value-of-a-generic-type.md @@ -0,0 +1,32 @@ +# Produce The Zero Value For A Generic Type + +While writing a _pop_ function that would work with slices of a generic type, I +ran into the issue of needing to produce a zero value of type `T` when +returning early for an empty slice. + +The way to arbitrarily get the zero value of a generic in Go is with `*new(T)`. + +I was able to use this in my `Pop` function like so: + +```go +func Pop[T any](slice []T) (T, error) { + if len(slice) == 0 { + return *new(T), fmt.Errorf("cannot pop an empty slice") + } + + lastItem := slice[len(slice)-1] + + slice = slice[:len(slice)-1] + + return lastItem, nil +} +``` + +If this is happening in multiple functions and we want a more self-documenting +approach, we can pull it out into a function `zero`: + +```go +func zero[T any]() T { + return *new(T) +} +```