GGistDev

Constants in Go

Constants are immutable, compile-time values. They improve clarity, safety, and performance. By default, constants are untyped and adapt to context.

Core ideas

  • Immutable: cannot change after declaration
  • Compile-time: evaluated by the compiler when possible
  • Untyped by default: adapt to assignment context

Basic and untyped constants

package main
import "fmt"

func main() {
    const msg = "Hello"     // untyped string
    const n = 42             // untyped number
    const r = 0.15           // untyped float
    const on = true          // untyped bool

    var i int = n      // ok: n adapts to int
    var f64 = r * 2.0  // ok: r adapts to float64

    fmt.Println(msg, i, f64, on)
}

Notes:

  • Untyped constants don’t overflow until given a type; they can represent arbitrarily large precision within spec limits

Groups

Group related constants to improve readability. Parentheses open a constant declaration block.

const (
    AppName    = "GistDev"
    AppVersion = "1.0.0"
    Port       = 8080
    Debug      = true
)

iota (auto-increment)

iota increments automatically within a constant block, letting you define sequences concisely (enums, bit sizes, flags).

package main
import "fmt"

func main() {
    const (
        Sunday = iota // 0
        Monday        // 1
        Tuesday       // 2
    )

    const (
        KB = 1 << (10 * iota) // 1, 1024, 1048576, ...
        MB
        GB
    )

    fmt.Println(Sunday, Monday, Tuesday)
    fmt.Println(KB, MB, GB)
}

Tips:

  • You can skip values with _ and compute from previous ones

Typed constants and enum-like patterns

package main
import "fmt"

type Status int
const (
    StatusPending Status = iota
    StatusRunning
    StatusDone
)

func (s Status) String() string {
    switch s {
    case StatusPending:
        return "Pending"
    case StatusRunning:
        return "Running"
    case StatusDone:
        return "Done"
    default:
        return "Unknown"
    }
}

func main() {
    s := StatusRunning
    fmt.Println(s, s.String())
}

Use typed constants to create safe, expressive APIs and avoid mixing unrelated values.

Constants vs variables

  • Constants: compile-time facts (timeouts, sizes, names)
  • Variables: runtime values (timestamps, counters, flags)
package main
import (
    "fmt"
    "time"
)

const (
    DefaultTimeout = 30 * time.Second
    MaxRetries     = 3
)

var (
    start = time.Now()
    connected bool
)

func main() {
    fmt.Println(DefaultTimeout, MaxRetries, start.IsZero(), connected)
}

Best practices

  • Prefer untyped consts for flexibility; use typed when you need strictness
  • Group related constants in const blocks; name clearly
  • Use iota for sequences; skip with _ if needed
  • Avoid magic numbers; replace with named constants
  • Document units (e.g., durations, sizes) in constant names or comments

Summary

  • Constants are compile-time, immutable values
  • iota helps define sequences succinctly
  • Typed constants enable safe, enum-like APIs
  • Use constants to make code clearer and cheaper at runtime