Searches like golang const array, golang constant array, go constant array, go const array, const array golang, golang array constant, golang array const, or golang constant slice usually hit the same language rule: const in Go only names compile-time values whose type is a boolean, rune, integer, floating-point, complex, or string (or a typed alias of those), built from constant expressions. A whole array or slice value is never a constant, so const xs = []int{1, 2, 3} and const xs = [3]int{1, 2, 3} both fail to compile. This page explains why, then lists practical patterns—including golang const string array style lists—for data you want to treat as fixed. For general constants, see Effective Go: Constants and the constants blog; for variables and globals; for functions that return data; for slices after you have a backing array.
Tested with Go 1.24 on Linux.
What the compiler allows as const
This is legal:
package main
import "fmt"
const (
piApprox = 355 / 113
label = "ready"
ok = true
)
func main() {
fmt.Println(piApprox, label, ok)
}You should see 3 ready true (integer division in the constant expression).
This is not legal (composite array/slice values are not constants):
const nums = [3]int{1, 2, 3} // compile error: not a constantThe same restriction answers golang constant slice: slices are always runtime values built from a pointer, length, and capacity.
golang const string array (one string, many fields)
Keep the list as a const string, then split when you need a []string:
package main
import (
"fmt"
"strings"
)
const envList = "dev,staging,prod"
func main() {
fields := strings.Split(envList, ",")
fmt.Println(fields)
}You should see [dev staging prod]. The string is constant; the slice is created at runtime and can still be modified—copy with append([]string(nil), fields...) if you want to protect callers from mutation.
go constant array: many const strings, one slice in init
When each entry is its own constant, assemble a []string once in init (still not a const slice, but every element comes from constants):
package main
import "fmt"
const (
envDev = "dev"
envProd = "prod"
)
var envs []string
func init() {
envs = []string{envDev, envProd}
}
func main() {
fmt.Println(envs)
}You should see [dev prod]. This fits go constant array–style configs where you want named constants but a single slice to range over.
Fixed array or slice as package-level data (not const)
Use an unexported var plus read-only access through functions if you want to hide mutation, or document that callers must not change shared state:
package main
import "fmt"
var defaultPorts = []int{80, 443, 8080}
func Ports() []int {
out := make([]int, len(defaultPorts))
copy(out, defaultPorts)
return out
}
func main() {
fmt.Println(Ports())
}You should see [80 443 8080]. Returning a copy avoids sharing the backing array (see append and slice growth for how slices alias memory).
Related constants with iota (not an array, but a table)
When people want a constant array golang of related numbers or strings, iota blocks are the idiomatic substitute:
package main
import "fmt"
const (
StatusPending = iota
StatusRunning
StatusDone
)
func main() {
fmt.Println(StatusPending, StatusRunning, StatusDone)
}You should see 0 1 2. Each name is its own const; you still cannot bundle them into a const []int.
Summary
Golang const array and go constant array do not exist as a single const binding: arrays and slices are composite runtime values, so the compiler rejects them in const declarations. Use const strings (plus strings.Split) for a golang const string array feel, build a slice from several const strings in init, use iota for families of related constants, or a package-level var with copying or discipline when you need a fixed list. Arrays remain fixed-length but mutable; const does not make them immutable.
References
- The Go Programming Language Specification — Constants
- Go blog: Constants
- Effective Go — Constants
- Append and slices

