Constants and Literals

Overview

Constants in Go are values determined at compile time that cannot be changed during program execution. Go distinguishes between typed and untyped constants, with untyped constants having special flexibility.

Declaring Constants

Basic Declaration

const Pi = 3.14159
const MaxSize = 1024
const Greeting = "Hello, World!"

Constant Block

const (
    StatusOK       = 200
    StatusNotFound = 404
    StatusError    = 500
)

Typed vs Untyped Constants

// Untyped constant (more flexible)
const untypedPi = 3.14159

// Typed constant (explicit type)
const typedPi float64 = 3.14159

Untyped Constants

Untyped constants have a kind but not a fixed type, allowing them to adapt:

const answer = 42  // Untyped integer constant

var i int = answer       // Works: becomes int
var f float64 = answer   // Works: becomes float64
var c complex128 = answer // Works: becomes complex128

Why This Matters

// Untyped constant can be used with any compatible type
const billion = 1e9

var i int64 = billion     // ✓ Works
var f float32 = billion   // ✓ Works

// Typed constant is locked to its type
const typedBillion int64 = 1e9
var f float64 = typedBillion  // ✗ Error: cannot use int64 as float64

Constant Kinds

Kind Examples
Boolean true, false
Integer 42, 0x2A, 0b101010
Floating-point 3.14, 6.022e23
Complex 1 + 2i
String "hello", `raw string`
Rune 'A', '世'

The iota Constant Generator

iota generates sequential integer constants, starting from 0 and incrementing by 1 for each constant in the block.

Basic Usage

const (
    Sunday = iota    // 0
    Monday           // 1
    Tuesday          // 2
    Wednesday        // 3
    Thursday         // 4
    Friday           // 5
    Saturday         // 6
)

Skip Values

const (
    _ = iota         // 0 (skipped)
    KB = 1 << (10 * iota)  // 1 << 10 = 1024
    MB                     // 1 << 20 = 1,048,576
    GB                     // 1 << 30 = 1,073,741,824
    TB                     // 1 << 40
)

Bit Flags with iota

const (
    FlagRead    = 1 << iota  // 1 (0001)
    FlagWrite                // 2 (0010)
    FlagExecute              // 4 (0100)
)

permissions := FlagRead | FlagWrite  // 3 (0011)

hasRead := permissions & FlagRead != 0   // true
hasExec := permissions & FlagExecute != 0 // false

Multiple iota in One Line

const (
    A, B = iota, iota + 10  // A=0, B=10
    C, D                    // C=1, D=11
    E, F                    // E=2, F=12
)

Reset iota

Each const block resets iota to 0:

const (
    First = iota   // 0
    Second         // 1
)

const (
    Third = iota   // 0 (reset!)
    Fourth         // 1
)

Constant Expressions

Constants can be computed from other constants at compile time:

const (
    SecondsPerMinute = 60
    MinutesPerHour   = 60
    SecondsPerHour   = SecondsPerMinute * MinutesPerHour
    SecondsPerDay    = SecondsPerHour * 24
)

Allowed in Constant Expressions

  • Arithmetic operators: +, -, *, /, %
  • Comparison operators: ==, !=, <, >, <=, >=
  • Logical operators: &&, ||, !
  • Bit operators: &, |, ^, <<, >>, &^
  • Built-in functions: len(), cap() (for some values), real(), imag(), complex()

Not Allowed

const x = math.Sin(0)  // Error: function call not allowed
const y = len(someVar)  // Error: variable not allowed

Numeric Literals

Integer Literals

decimal := 42          // Base 10
binary := 0b101010     // Base 2 (Go 1.13+)
octal := 0o52          // Base 8 (Go 1.13+)
oldOctal := 052        // Base 8 (legacy)
hex := 0x2A            // Base 16

Floating-Point Literals

f1 := 3.14
f2 := .5               // 0.5
f3 := 1.               // 1.0
f4 := 6.022e23         // Scientific notation
f5 := 6.022E23         // Same
f6 := 1.5e-10          // 0.00000000015

Hexadecimal Floats (Go 1.13+)

f := 0x1.fp+2  // (1 + 15/16) * 2^2 = 7.75

Imaginary Literals

i := 3i
c := 2 + 3i

Digit Separators

Go 1.13+ allows underscores in numeric literals for readability:

billion := 1_000_000_000
binary := 0b_1010_1010
hex := 0xFF_FF_FF_FF

String and Rune Literals

Interpreted Strings

s := "Hello, World!\n"  // Escape sequences processed
s := "Tab:\tNewline:\n"
s := "Quote: \"Go\""

Escape Sequences

Escape Meaning
\n Newline
\t Tab
\\ Backslash
\" Double quote
\r Carriage return
\xNN Hex byte
\uNNNN Unicode code point (4 hex)
\UNNNNNNNN Unicode code point (8 hex)

Raw String Literals

raw := `No escape sequences: \n \t \\
Multiple lines work!
Useful for regex: \d+\.\d+`

Rune Literals

r1 := 'A'      // 65
r2 := '世'     // 19990
r3 := '\n'     // 10
r4 := '\x41'   // 65 (hex)
r5 := '\u4e16' // 19990 (unicode)

Common Patterns

Enum Pattern

type Status int

const (
    StatusPending Status = iota
    StatusApproved
    StatusRejected
)

func (s Status) String() string {
    switch s {
    case StatusPending:
        return "Pending"
    case StatusApproved:
        return "Approved"
    case StatusRejected:
        return "Rejected"
    default:
        return "Unknown"
    }
}

Configuration Constants

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

Summary

Concept Description
const Compile-time immutable value
Untyped Flexible, adapts to context
Typed Fixed to a specific type
iota Auto-incrementing generator
Literal Numeric, string, or rune value in source