TIL: wrapping my head around Go’s “iota”
Tags: go, iota, tutorial
Published: 2023-02-11 09:15:45

---
title: TIL: wrapping my head around Go’s “iota”
published: true
description: Go’s “iota”
tags: go, iota, tutorial
canonical_url: https://tomdeneire.medium.com/til-wrapping-my-head-around-gos-iota-38a81d5f402a
series_name: TIL
---

*TIL (“Today I learned”) are shorter, less-researched posts that I typically write to help organize my thoughts and solidify things I have learned while working. I post them here as a personal archive and of course for others to possibly benefit from.*

![Photo by [Kelly Sikkema](https://unsplash.com/@kellysikkema?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://cdn-images-1.medium.com/max/6000/0*Sj-lxNZK6u3b7G2x)
Photo by [Kelly Sikkema](https://unsplash.com/@kellysikkema?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

## Iota

A few days ago, I happened upon the `iota` identifier in Go.

I remembered seeing it before, but it’s still pretty rare, so I looked up the definition of `iota` in the [documentation](https://pkg.go.dev/builtin#pkg-constants):

    const iota = 0 // Untyped int.
>  iota is a predeclared identifier representing the untyped integer ordinal number of the current const specification in a (usually parenthesized) const declaration. It is zero-indexed.

## ¿Qué?

Upon reading this (several times over actually) I must confess I still didn’t really understand what `iota` was or did. And while the [language specification](https://go.dev/ref/spec#Iota) is more explicit and has examples, it is not much clearer:

>  Within a constant declaration, the predeclared identifier iota represents successive untyped integer constants. Its value is the index of the respective ConstSpec in that constant declaration, starting at zero. It can be used to construct a set of related constants

Some additional browsing, in [Golang by Example](https://golangbyexample.com/iota-in-golang/), for instance, reveals that `iota` can be used to implement enums in Go. Like so:

    type Size uint8
    
    const (
    	small Size = iota
    	medium
    	large
    	extraLarge
    )

which is effectively the same as:

    type Size uint8
    
    const (
     small      Size = 0
     medium     Size = 1
     large      Size = 2
     extraLarge Size = 3
    )

and, indeed, a cleaner solution than defining `Size` like so:

    type Size string
    
    const (
     small      Size = "small"
     medium     Size = "medium"
     large      Size = "large"
     extraLarge Size = "extraLarge"
    )

## The power of a great example

Even after these examples, I didn’t really see much benefit in `iota`, apart from its auto-increment function.

It was only when I read the example from [Effective Go](https://go.dev/doc/effective_go), that I realised the true power of `iota`:

    type ByteSize float64
    
    const (
        _           = iota // ignore first value by assigning to blank identifier
        KB ByteSize = 1 << (10 * iota)
        MB
        GB
        TB
        PB
        EB
        ZB
        YB
    )

    func (b ByteSize) String() string {
        switch {
        case b >= YB:
            return fmt.Sprintf("%.2fYB", b/YB)
        case b >= ZB:
            return fmt.Sprintf("%.2fZB", b/ZB)
        case b >= EB:
            return fmt.Sprintf("%.2fEB", b/EB)
        case b >= PB:
            return fmt.Sprintf("%.2fPB", b/PB)
        case b >= TB:
            return fmt.Sprintf("%.2fTB", b/TB)
        case b >= GB:
            return fmt.Sprintf("%.2fGB", b/GB)
        case b >= MB:
            return fmt.Sprintf("%.2fMB", b/MB)
        case b >= KB:
            return fmt.Sprintf("%.2fKB", b/KB)
        }
        return fmt.Sprintf("%.2fB", b)
    }

You use iota to define constants, but that doesn’t mean the constant cannot apply arithmetic to an `iota`. So, through clever use of the bitwise shift operator `<<`, you can make iota do the heavy lifting for you in defining byte units!

What a great example to explain the concrete usage of an abstract notion! I only wish examples like this would be included in the official documentation instead of a document that describes itself as “tips for writing clear, idiomatic Go code”…

---
*Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out [https://tomdeneire.github.io](https://tomdeneire.github.io/)*