Question
Is there an idiomatic naming convention for constants in Go? In particular, should constants use uppercase names as they often do in C, or should they follow Go's usual naming style?
For example:
const MAX_RETRIES = 3 // C-style uppercase
or:
const maxRetries = 3 // Go-style mixedCaps
Short Answer
Go does not use a special all-uppercase naming convention for constants. Constants follow the same naming rules as variables, functions, and types: use mixedCaps, and capitalize the first letter only when the name must be exported from its package. By the end, you will know how to name package-level and local constants idiomatically.
Concept
In Go, whether an identifier is a constant does not determine its casing. Go code generally avoids ALL_CAPS_WITH_UNDERSCORES, a convention common in C and some other languages.
Instead, Go uses casing to express visibility:
- A name beginning with a lowercase letter is unexported: it is accessible only within its package.
- A name beginning with an uppercase letter is exported: other packages can access it.
const maxRetries = 3 // unexported package constant
const MaxRetries = 3 // exported package constant
Both are constants. The initial letter answers a different question: who should be able to use this name?
This consistency matters because Go code is designed to be read quickly. A reader can apply one naming rule to constants, variables, functions, methods, and types rather than memorizing a separate uppercase rule for constants.
For multiword names, use mixedCaps without underscores:
const defaultTimeoutSeconds = 30
const DefaultTimeoutSeconds = 30
For common initialisms, use their conventional all-capital form within the name:
const maxHTTPRedirects = 10
const defaultURL = "https://example.com"
const APIVersion = "v1"
Mental Model
Think of a Go identifier as a label on a box.
- A label starting with a lowercase letter means: this box stays inside this package.
- A label starting with an uppercase letter means: this box is part of the package's public shelf, so other packages may use it.
The fact that the box contains a value that cannot change—a constant—does not change how the label is written. In Go, casing communicates visibility, not mutability.
Syntax and Examples
Declare a constant with const:
const name = value
Use a lowercase initial for an internal constant:
package retry
const defaultMaxAttempts = 3
func MaxAttempts() int {
return defaultMaxAttempts
}
Use an uppercase initial only when callers in other packages need the constant:
package protocol
const DefaultPort = 8080
A different package can use the exported name:
package main
import (
"fmt"
"example.com/project/protocol"
)
func main() {
fmt.Println(protocol.DefaultPort)
}
For related constants, group them in a const block:
const (
minPasswordLength = 8
maxPasswordLength = 128
)
The names remain mixedCaps; grouping does not require uppercase names.
Step by Step Execution
Consider this package:
package config
const defaultPort = 8080
const DefaultHost = "localhost"
func Address() string {
return DefaultHost + ":8080"
}
Step by step:
defaultPortis a constant. Because it begins with lowercased, only code in packageconfigcan refer to it.DefaultHostis also a constant. Because it begins with uppercaseD, another package may refer to it asconfig.DefaultHost.Addressis exported for the same reason: it starts withA.- When
Address()runs, it evaluates the constant expressionDefaultHost + ":8080"and returns"localhost:8080". - Both constant names follow Go's naming convention. Their casing differs because their intended package visibility differs.
Real World Use Cases
Constants are useful when a value has a stable meaning and should not be changed at runtime.
- Protocol values: HTTP status codes, header names, API versions, and default ports.
- Application defaults: retry limits, pagination sizes, timeout durations, and maximum upload sizes.
- Domain states: order statuses, permission levels, event kinds, or file format identifiers.
- Bit flags: permission or feature flags declared with typed constants.
- Configuration keys: environment-variable names or JSON field-related keys, when a repeated string should have one authoritative name.
Example of internal defaults:
const (
defaultPageSize = 25
maxPageSize = 100
)
These values are implementation details, so lowercase names are appropriate. If users of your package must intentionally depend on a value, expose a carefully named exported constant instead.
Real Codebase Usage
In real Go packages, constants are usually kept as narrow in scope as possible.
Keep implementation details unexported
const defaultTimeout = 5 * time.Second
This lets the package change its internal default later without making it part of the public API.
Export only intentional API values
const MaxPageSize = 100
Export this when package users need the limit to validate their own input or build an interface around it.
Use guard clauses with constants
const maxItems = 100
func Process(items []string) error {
if len(items) > maxItems {
return fmt.Errorf("too many items: maximum is %d", maxItems)
}
return nil
}
Use typed constants for meaningful categories
package order
type Status string
const (
StatusPending Status = "pending"
StatusPaid Status = "paid"
StatusShipped Status = "shipped"
)
The Status prefix makes exported names clear at call sites, such as order.StatusPaid. The names still use mixedCaps.
Use iota for related enumerations
type Level int
const (
LevelInfo Level = iota
LevelWarning
LevelError
)
Use descriptive type and constant names rather than relying on uppercase formatting to signal that they are constants.
Common Mistakes
Using C-style all caps by default
This compiles, but is not idiomatic Go:
const MAX_RETRIES = 3
Prefer:
const maxRetries = 3
Or, if it is intentionally public:
const MaxRetries = 3
Using underscores in ordinary Go names
const default_timeout_seconds = 30
Prefer Go's mixedCaps style:
const defaultTimeoutSeconds = 30
Exporting every constant
const DefaultTimeout = 5 * time.Second
This may be wrong if only the current package needs the value. Exported identifiers become part of the package API and are harder to change without affecting users. Prefer defaultTimeout unless external callers need it.
Forgetting that capitalization affects accessibility
// package config
const defaultPort = 8080
// package main
fmt.Println(config.defaultPort) // does not compile
The unexported name is inaccessible outside config. Use config.DefaultPort only if DefaultPort is intentionally exported.
Treating initialisms as ordinary words
const defaultUrl = "https://example.com"
Prefer conventional initialism casing:
const defaultURL = "https://example.com"
Common examples include API, HTTP, ID, IP, JSON, SQL, TCP, URL, and UUID.
Comparisons
| Style or feature | Example | Meaning in Go | When to use it |
|---|---|---|---|
Unexported mixedCaps constant | const maxRetries = 3 | Available only in its package | Internal defaults and implementation details |
Exported mixedCaps constant | const MaxRetries = 3 | Available to importing packages | Deliberate public API values |
| C-style uppercase constant | const MAX_RETRIES = 3 | Valid Go, but uncommon | Usually avoid in idiomatic Go |
| Underscore-separated name | const max_retries = 3 | Valid in some contexts, but non-idiomatic for Go identifiers | Usually avoid; use maxRetries |
| Variable | var maxRetries = 3 | Value may be reassigned | Use when the value must change |
| Constant | const maxRetries = 3 | Compile-time constant value | Use for fixed values and constant expressions |
A Go constant is also different from a readonly variable in languages that have one: a constant has language-level restrictions and participates in constant expressions. It cannot be assigned a value that requires runtime computation, such as the result of most function calls.
Cheat Sheet
// Internal to a package
const defaultRetries = 3
// Public package API
const DefaultRetries = 3
// Multiword names: mixedCaps
const defaultTimeoutSeconds = 30
// Common initialisms stay uppercase
const defaultURL = "https://example.com"
const maxHTTPRedirects = 10
// Group related values
const (
minAge = 18
maxAge = 120
)
// Typed constants
type Status string
const (
StatusPending Status = "pending"
StatusPaid Status = "paid"
)
- Do not use
ALL_CAPSmerely because a value is a constant. - Uppercase the first letter only to export the identifier.
- Prefer no underscores in ordinary Go identifiers.
- Keep constants unexported unless external packages need them.
- Use
gofmtfor formatting; it does not rename identifiers.
FAQ
Should Go constants be uppercase?
No. Idiomatic Go constants use mixedCaps. Start with uppercase only when the constant must be exported from its package.
Why does Go not use ALL_CAPS for constants?
Go uses initial capitalization to indicate whether an identifier is exported. It applies the same naming style to constants, variables, functions, and types for consistency.
Can I write const MAX_SIZE = 100 in Go?
Yes, it is valid Go syntax. However, most Go code would name it maxSize or MaxSize instead.
When should a constant start with a capital letter?
When it is a deliberate part of your package's public API and other packages need to access it.
Should Go constant names contain underscores?
Usually no. Prefer defaultBufferSize rather than default_buffer_size.
How should I capitalize URL, HTTP, and ID in Go names?
Use conventional initialism casing: serverURL, HTTPClient, and userID.
Is const always better than var for fixed values?
Use const when the value is a compile-time constant. Use var when initialization requires runtime work, such as calling a function or creating a map.
Should every package constant be exported for reuse?
No. Exporting creates a public dependency. Keep it lowercase when it is only an internal implementation detail.
Mini Project
Description
Create a small package for validating page-size requests. It demonstrates idiomatic names for internal limits, exported package constants, and typed constant values used by callers.
Goal
Build a Go program that accepts a requested page size, applies a default, and rejects values outside the supported range.
Requirements
- Declare an exported
DefaultPageSizeconstant with a value of 25. - Declare an exported
MaxPageSizeconstant with a value of 100. - Keep the minimum page size as an unexported constant.
- Write a
ValidatePageSizefunction that returns the default when the requested size is zero. - Return an error when a requested size is below the minimum or above the maximum.
- Print the result for a valid request and an invalid request.
Keep learning
Related questions
Are Go Maps Passed by Value or Reference?
Learn Go map parameter and return semantics: maps are passed by value, while copies share underlying data. Know when map pointers are useful.
Authentication for Go REST APIs: Sessions, Tokens, and Middleware
Learn practical authentication patterns for Go REST APIs, including password hashing, server sessions, bearer tokens, middleware, and security rules.
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.