Question
I can declare a constant string like this:
const ascii = "abcdefghijklmnopqrstuvwxyz"
But these attempts to declare a constant collection of floating-point values do not work:
const letter_goodness []float32 = { .0817, .0149, .0278, .0425, .1270, .0223, .0202, .0609, .0697, .0015, .0077, .0402, .0241, .0675, .0751, .0193, .0009, .0599, .0633, .0906, .0276, .0098, .0236, .0015, .0197, .0007 }
const letter_goodness = { .0817, .0149, .0278, .0425, .1270, .0223, .0202, .0609, .0697, .0015, .0077, .0402, .0241, .0675, .0751, .0193, .0009, .0599, .0633, .0906, .0276, .0098, .0236, .0015, .0197, .0007 }
const letter_goodness = []float32{ .0817, .0149, .0278, .0425, .1270, .0223, .0202, .0609, .0697, .0015, .0077, .0402, .0241, .0675, .0751, .0193, .0009, .0599, .0633, .0906, .0276, .0098, .0236, .0015, .0197, .0007 }
The string constant works, but the array or slice versions do not. How do you correctly declare and initialize a constant array of floats in Go?
Short Answer
By the end of this page, you will understand why Go allows const for simple compile-time values like strings and numbers, but not for arrays or slices. You will also learn the correct way to store fixed float data in Go using variables, arrays, slices, and patterns that make the data effectively read-only.
Concept
In Go, const is only for constant values known at compile time. That includes values such as:
- numbers
- booleans
- strings
- rune constants
It does not include:
- arrays
- slices
- maps
- structs
That is why this works:
const ascii = "abcdefghijklmnopqrstuvwxyz"
A string can be a constant in Go.
But this does not work:
const letterGoodness = []float32{0.0817, 0.0149}
A slice is not a constant type. It is a runtime data structure containing a pointer, length, and capacity.
Similarly, arrays are also not allowed as constants in Go. Even though an array has fixed size, Go still does not permit arrays in const declarations.
So if you want fixed float data, the usual solution is to use a package-level variable:
var letterGoodness = []float32{0.0817, 0.0149, 0.0278}
or a package-level array:
Mental Model
Think of Go const values as values printed directly into the program at compile time.
- A number constant is like writing a number on paper.
- A string constant is like printing a fixed label.
- A slice is more like a small container object that points to data somewhere else.
Go allows const for simple printed values, but not for containers.
So:
const "hello"works because it is a simple fixed value.const []float32{...}does not work because a slice is a runtime structure.
If you need a fixed collection, use a variable and treat it as read-only.
Syntax and Examples
The correct syntax depends on whether you want an array or a slice.
1. Package-level array
Use an array if the size is fixed and known.
var letterGoodness = [...]float32{
0.0817, 0.0149, 0.0278, 0.0425, 0.1270, 0.0223, 0.0202,
0.0609, 0.0697, 0.0015, 0.0077, 0.0402, 0.0241, 0.0675,
0.0751, 0.0193, 0.0009, 0.0599, 0.0633, 0.0906, 0.0276,
0.0098, 0.0236, 0.0015, 0.0197, 0.0007,
}
[...]float32 tells Go to count the number of elements automatically.
2. Package-level slice
Use a slice if you want slice behavior.
var letterGoodness = []float32{
0.0817, , , , , , ,
, , , , , , ,
, , , , , , ,
, , , , ,
}
Step by Step Execution
Consider this example:
package main
import "fmt"
var weights = [...]float32{0.5, 1.5, 2.5}
func main() {
fmt.Println(weights)
fmt.Println(weights[1])
}
Here is what happens step by step:
- Go sees
var weights = [...]float32{0.5, 1.5, 2.5}. varmeans this is a variable, not a constant.[...]float32means:- create an array
- element type is
float32 - count the length from the values provided
- Go creates an array of length 3.
- The values are stored in order:
- index
0→0.5 - index
1→1.5 - index
2→2.5
- index
- In
main, prints the full array.
Real World Use Cases
Even though Go does not support constant arrays or slices, fixed collections are common in real programs.
Common uses
- Lookup tables: letter frequencies, scoring tables, conversion factors
- Configuration defaults: default ports, retry delays, allowed file extensions
- Static reference data: month names, country codes, status labels
- Parsing and validation: known token lists, keyword lists, accepted values
- Data science or analysis scripts: weight values, coefficients, sample distributions
Example: letter frequency data
var englishLetterFrequency = [...]float32{
0.0817, 0.0149, 0.0278, 0.0425, 0.1270, 0.0223, 0.0202,
0.0609, 0.0697, 0.0015, 0.0077, 0.0402, 0.0241, 0.0675,
0.0751, 0.0193, 0.0009, 0.0599, 0.0633, 0.0906, 0.0276,
0.0098, 0.0236, 0.0015, 0.0197, 0.0007,
}
This is ideal for algorithms that score text, detect language, or analyze letter usage.
Real Codebase Usage
In real Go codebases, developers usually handle “constant-like collections” with one of these patterns.
1. Package-level unexported variable
var defaultTimeouts = []int{1, 2, 5}
This works when only the package uses the data.
2. Unexported data with exported accessor
var defaultTimeouts = [...]int{1, 2, 5}
func DefaultTimeouts() []int {
out := make([]int, len(defaultTimeouts))
copy(out, defaultTimeouts[:])
return out
}
This prevents callers from modifying the original shared data.
3. Guarding against mutation
If shared data must not change, avoid returning the original slice directly.
Broken pattern:
var defaults = []int{1, 2, 3}
func [] {
defaults
}
Common Mistakes
1. Trying to use const with a slice
Broken code:
const values = []float32{1.1, 2.2}
Why it fails:
- slices are not valid constant types in Go
Use this instead:
var values = []float32{1.1, 2.2}
2. Trying to use const with an array
Broken code:
const values = [2]float32{1.1, 2.2}
Why it fails:
- arrays also cannot be declared as constants in Go
Use this instead:
var values = [2]float32{1.1, 2.2}
3. Forgetting the type in a composite literal
Broken code:
Comparisons
| Concept | Example | Can use const? | Size fixed? | Can be resized? |
|---|---|---|---|---|
| String constant | const s = "abc" | Yes | N/A | No |
| Number constant | const n = 10 | Yes | N/A | No |
| Array | var a = [3]float32{1,2,3} | No | Yes | No |
| Slice | var s = []float32{1,2,3} | No | No | Yes |
Cheat Sheet
Quick rules
- Go
constworks for:- numbers
- strings
- booleans
- runes
- Go
constdoes not work for:- arrays
- slices
- maps
- structs
Valid examples
const name = "go"
const max = 10
const enabled = true
Invalid examples
const nums = []int{1, 2, 3}
const nums = [3]int{1, 2, 3}
Use these instead
Fixed-size array
var nums = [...]float32{1.1, 2.2, 3.3}
Slice
FAQ
Why can't I declare a constant slice in Go?
Because slices are runtime data structures, not compile-time constant values.
Can I declare a constant array in Go?
No. Go does not allow arrays as const values either.
What should I use instead of a constant array?
Use a package-level var with an array or slice literal.
How do I make slice data read-only in Go?
Go has no built-in read-only slice type. A common pattern is to keep the original data private and return a copy.
Should I use an array or a slice for fixed data?
Use an array when the size is truly fixed and meaningful. Use a slice when you want more flexible APIs.
Is a string different from a slice in Go constants?
Yes. A string can be a constant, but a slice cannot.
Can callers modify a slice returned from a function?
Yes, unless you return a copy. Returning the original slice exposes shared mutable data.
Mini Project
Description
Build a small Go utility that stores English letter frequency data and looks up the score for a given lowercase letter. This demonstrates how to keep fixed reference data in Go using an array instead of an invalid const collection.
Goal
Create a program that maps letters a to z to their frequency values and prints the value for selected letters.
Requirements
- Store the alphabet as a string constant.
- Store the frequency values in a package-level array or slice.
- Write a function that accepts a lowercase letter and returns its frequency.
- Return
0for characters outsideatoz.
Keep learning
Related questions
Automatic Build Versioning in Go: Embed Incrementing Build Numbers
Learn how to add automatic build versioning in Go using linker flags, build metadata, CI counters, and Git-based version values.
Blank Identifier Imports in Go: What `_` Means in an Import Statement
Learn what `_` means in a Go import, why blank identifier imports run package init code, and when to use them safely.
Calling Functions Across Files in the Same Go Package
Learn how Go uses packages across multiple files, why functions may appear undefined, and how to organize code correctly.