Skip to content

Constants ​

Before You Start

  • Applies to: Go 1.21+ (examples verified with Go 1.22) · Prerequisites: Variables · Read time: about 5 min

The value of constants in Go cannot be changed at runtime. Once assigned, it cannot be modified. Its value can only come from:

  • Literals
  • Other constant identifiers
  • Constant expressions
  • Type conversions that result in constants
  • iota

Constants can only be basic data types and cannot be:

  • Other types besides basic types, such as structs, interfaces, slices, arrays, etc.
  • Function return values

The value of constants cannot be modified, otherwise it won't compile.

Initialization ​

Constants are declared using the const keyword. A constant must be initialized with a value when declared, and the type of the constant can be omitted.

go
const name string = "Jack" // Literal

const msg = "hello world" // Literal

const num = 1 // Literal

const numExpression = (1+2+3) / 2 % 100 + num // Constant expression

If you only declare without assigning a value, it won't compile:

go
const name string

The compiler will report an error:

missing init expr for name

Batch declaration of constants can use () to improve readability. Multiple () can be used to achieve grouping.

go
const (
   Count = 1
   Name  = "Jack"
)

const (
   Size = 16
   Len  = 25
)

In the same constant group, constants after an assigned constant don't need to be assigned. Their value defaults to the previous value:

go
const (
  A = 1
  B // 1
  C // 1
  D // 1
  E // 1
)

iota ​

iota is a built-in constant identifier, usually used to represent an untyped integer ordinal in a constant declaration. It is generally used within parentheses.

go
const iota = 0

Let's look at some usage cases:

go
const (
   Num = iota // 0
   Num1 // 1
   Num2 // 2
   Num3 // 3
   Num4 // 4
)

Can also be written like this:

go
const (
   Num = iota*2 // 0
   Num1 // 2
   Num2 // 4
   Num3 // 6
   Num4 // 8
)

Or:

go
const (
   Num = iota << 2*3 + 1 // 1
   Num1 // 13
   Num2 // 25
   Num3 = iota // 3
   Num4 // 4
)

From the examples above, we can see that iota is incremental. The first constant using iota is assigned an expression, and based on the ordinal value changes, it will automatically assign values to subsequent constants until a new const resets it. This ordinal is actually the relative line number of the code, relative to the first line of the current group.

go
const (
  Num  = iota<<2*3 + 1 // 1 First line
  Num2 = iota<<2*3 + 1 // 13 Second line
  _ // 25 Third line
  Num3 //37 Fourth line
  Num4 = iota // 4 Fifth line
  _ // 5 Sixth line
  Num5 // 6 Seventh line
)

The example uses the anonymous identifier _ to occupy a line. You can see that the value of iota is essentially the difference between the line where iota is located and the first line of the current const group. Different const groups don't affect each other.

Enums ​

Go doesn't have a separate data type for enums, unlike other languages which usually have an enum. Generally in Go, enums are implemented through custom types + const + iota. Here is a simple example:

go
type Season uint8

const (
  Spring Season = iota
  Summer
  Autumn
  Winter
)

These enums are actually numbers. Go also doesn't support direct conversion to strings, but we can add methods to custom types to return their string representation by implementing the Stringer interface.

go
func (s Season) String() string {
  switch s {
  case Spring:
    return "spring"
  case Summer:
    return "summer"
  case Autumn:
    return "autumn"
  case Winter:
    return "winter"
  }
  return ""
}

This is a simple enum implementation. You can also use the official tool Stringer to automatically generate enums.

However, it has the following disadvantages:

  • Type unsafe, because Season is a custom type, other numbers can be forcibly converted to this type

    go
    Season(6)
  • Tedious, string representation needs to be implemented manually

  • Weak expressiveness, because const only supports basic data types, these enum values can only be represented with strings and numbers

Why doesn't Go support enums at the language level is something I really don't understand. I think it would definitely be more beneficial than detrimental.

Complete Example ​

The program below runs as-is: copy it into a file and execute go run main.go, or paste it into the Go Playground.

go
package main

import "fmt"

// iota: the first constant in a const block is 0, then increments per ConstSpec
const (
	KB = 1 << (10 * (iota + 1))
	MB
	GB
)

// Typed enum-style constants with iota
type Weekday int

const (
	Sunday Weekday = iota
	Monday
	Tuesday
)

func main() {
	fmt.Println(KB, MB, GB)
	fmt.Println(Sunday, Monday, Tuesday)

	const pi = 3.14159
	const greeting = "hello"
	fmt.Println(pi, greeting)
}

Expected output:

text
1024 1048576 1073741824
0 1 2
3.14159 hello

Common Pitfalls ​

  • Constants cannot be assigned to or take an address. const c = 1; c = 2 and &c are both compile errors.
  • iota restarts in every const block and only advances per ConstSpec. Use _ = iota to skip values.
  • Parenthesize bit-shift combinations with iota. Writing 1 << 10 * (iota + 1) groups as (1 << 10) * (iota + 1), which is not what most people expect.
  • Only basic types can be constants. Slices, maps, structs and arrays cannot be const; use package-level var instead.
  • Untyped constants take type from context. const x = 1 is untyped and can be used as int or float64; once you add an explicit type, conversions become mandatory.

Change Log ​

  • 2026-10-14: Added "Before You Start" notes, a complete runnable example with expected output, common pitfalls, and this change log.

Golang by www.golangdev.cn · Adapted in part from Golang 中文学习文档 (MIT, © 寒江蓑笠翁)