Question

Go Constant Naming Conventions: Idiomatic const Names

goconstantsnaming-conventions

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.

Take Quiz

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:

  1. defaultPort is a constant. Because it begins with lowercase d, only code in package config can refer to it.
  2. DefaultHost is also a constant. Because it begins with uppercase D, another package may refer to it as config.DefaultHost.
  3. Address is exported for the same reason: it starts with A.
  4. When Address() runs, it evaluates the constant expression DefaultHost + ":8080" and returns "localhost:8080".
  5. 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.

Take Quiz

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 featureExampleMeaning in GoWhen to use it
Unexported mixedCaps constantconst maxRetries = 3Available only in its packageInternal defaults and implementation details
Exported mixedCaps constantconst MaxRetries = 3Available to importing packagesDeliberate public API values
C-style uppercase constantconst MAX_RETRIES = 3Valid Go, but uncommonUsually avoid in idiomatic Go
Underscore-separated nameconst max_retries = 3Valid in some contexts, but non-idiomatic for Go identifiersUsually avoid; use maxRetries
Variablevar maxRetries = 3Value may be reassignedUse when the value must change
Constantconst maxRetries = 3Compile-time constant valueUse 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.

Take Quiz

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_CAPS merely 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 gofmt for 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.

Take Quiz

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

  1. Declare an exported DefaultPageSize constant with a value of 25.
  2. Declare an exported MaxPageSize constant with a value of 100.
  3. Keep the minimum page size as an unexported constant.
  4. Write a ValidatePageSize function that returns the default when the requested size is zero.
  5. Return an error when a requested size is below the minimum or above the maximum.
  6. Print the result for a valid request and an invalid request.
Take Quiz

Keep learning

Related questions

View more