goconst

package module
v1.10.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 27, 2026 License: MIT Imports: 16 Imported by: 62

README

goconst

Find repeated strings that could be replaced by a constant.

Motivation

There are obvious benefits to using constants instead of repeating strings, mostly to ease maintenance. Cannot argue against changing a single constant versus many strings.

While this could be considered a beginner mistake, across time, multiple packages and large codebases, some repetition could have slipped in.

How it works

goconst detects string (and optionally number) literals that appear multiple times and could be replaced by a constant.

A few things to keep in mind:

  • Exact literal matching — goconst compares complete, unquoted literal values. Repeated substrings inside larger strings are not detected (e.g., a shared prefix across two different string literals will not be reported).
  • const declarations are skipped by default — constant values are only analyzed when -match-constant (match strings against existing constants) or -find-duplicates (find constants sharing the same value) is enabled.
  • String length is measured in runes, not bytes, so multi-byte Unicode characters are counted correctly against -min-length.
Get Started
$ go install github.com/jgautheron/goconst/cmd/goconst@latest
$ goconst ./...
Usage
Usage:

  goconst ARGS <directory> [<directory>...]

Flags:

  -ignore                     exclude files matching the given regular expression
  -ignore-strings             exclude strings matching the given regular expression
  -ignore-tests               exclude tests from the search (default: true)
  -min-occurrences            report from how many occurrences (default: 2)
  -min-length                 only report strings with the minimum given length (default: 3)
  -match-constant             look for existing constants matching the strings
  -find-duplicates            look for constants with identical values
  -eval-const-expr            enable evaluation of constant expressions (e.g., Prefix + "suffix")
  -ignore-calls               ignore string literals in calls to these functions (comma separated)
  -ignore-composite-literals  ignore string literals inside composite literals
  -numbers                    search also for duplicated numbers
  -min                        minimum value, only works with -numbers
  -max                        maximum value, only works with -numbers
  -output                     output formatting (text or json)
  -set-exit-status            Set exit status to 2 if any issues are found
  -grouped                    print single line per match, only works with -output text

Examples:

  goconst ./...
  goconst -ignore "yacc|\.pb\." $GOPATH/src/github.com/cockroachdb/cockroach/...
  goconst -min-occurrences 3 -output json $GOPATH/src/github.com/cockroachdb/cockroach
  goconst -numbers -min 60 -max 512 .
  goconst -min-occurrences 5 $(go list -m -f '{{.Dir}}')
  goconst -eval-const-expr -match-constant . # Matches constant expressions like Prefix + "suffix"
  goconst -ignore-calls slog.Info,slog.Warn,fmt.Errorf ./... # Ignore strings in logging/error calls
Development
Running Tests

The project includes a comprehensive test suite. To run the tests:

# Run all tests
go test ./...

# Run tests with verbose output
go test -v ./...

# Run tests with race detector
go test -race ./...

# Run benchmarks
go test -bench=. ./...

# Check test coverage
go test -cover ./...
Contributing

Contributions are welcome! Before submitting a PR:

  1. Make sure all tests pass
  2. Add tests for new functionality
  3. Ensure your code passes linting checks
  4. Update documentation as needed
Other static analysis tools
  • gogetimports: Get a JSON-formatted list of imports.
  • usedexports: Find exported variables that could be unexported.
License

MIT

Documentation

Overview

Package goconst finds repeated strings that could be replaced by a constant.

There are obvious benefits to using constants instead of repeating strings, mostly to ease maintenance. Cannot argue against changing a single constant versus many strings. While this could be considered a beginner mistake, across time, multiple packages and large codebases, some repetition could have slipped in.

Index

Constants

This section is empty.

Variables

View Source
var ByteBufferPool = sync.Pool{
	New: func() interface{} {
		slice := make([]byte, 0, 8*1024)
		return &slice
	},
}

ByteBufferPool is a pool for temporary byte slices

View Source
var ExtendedPosPool = sync.Pool{
	New: func() interface{} {
		slice := make([]ExtendedPos, 0, 8)
		return &slice
	},
}

ExtendedPosPool is a pool for slices of ExtendedPos

View Source
var FileReaderPool = sync.Pool{
	New: func() interface{} {

		return make([]byte, 32*1024)
	},
}

FileReaderPool is a pool of byte buffers used for reading files

View Source
var StringBuilderPool = sync.Pool{
	New: func() interface{} {
		return new(strings.Builder)
	},
}

StringBuilderPool is a pool of string builders to reduce memory allocations

View Source
var StringInternPool = sync.Map{}

StringInternPool is a pool for deduplicating strings to reduce memory usage

Functions

func GetByteBuffer added in v1.8.0

func GetByteBuffer() []byte

GetByteBuffer retrieves a byte buffer from the pool

func GetStringBuilder added in v1.8.0

func GetStringBuilder() *strings.Builder

GetStringBuilder retrieves a string builder from the pool

func InternString added in v1.8.0

func InternString(s string) string

InternString returns a deduplicated reference to the given string to reduce memory usage when the same string appears multiple times

func PutByteBuffer added in v1.8.0

func PutByteBuffer(buf []byte)

PutByteBuffer returns a byte buffer to the pool

func PutExtendedPosBuffer added in v1.8.0

func PutExtendedPosBuffer(slice []ExtendedPos)

PutExtendedPosBuffer returns an ExtendedPos slice to the pool

func PutStringBuilder added in v1.8.0

func PutStringBuilder(sb *strings.Builder)

PutStringBuilder returns a string builder to the pool after resetting it

Types

type Config

type Config struct {
	// IgnoreStrings is a list of regular expressions to filter strings
	IgnoreStrings []string
	// IgnoreTests indicates whether test files should be excluded
	IgnoreTests bool
	// MatchWithConstants enables matching strings with existing constants
	MatchWithConstants bool
	// MinStringLength is the minimum length a string must have to be reported
	MinStringLength int
	// MinOccurrences is the minimum number of occurrences required to report a string
	MinOccurrences int
	// ParseNumbers enables detection of duplicated numbers
	ParseNumbers bool
	// NumberMin sets the minimum value for reported number matches
	NumberMin int
	// NumberMax sets the maximum value for reported number matches
	NumberMax int
	// ExcludeTypes allows excluding specific types of contexts
	ExcludeTypes map[Type]bool
	// FindDuplicates enables finding constants whose values match existing constants in other packages.
	FindDuplicates bool
	// EvalConstExpressions enables evaluation of constant expressions like Prefix + "suffix"
	EvalConstExpressions bool
	// IgnoreFunctions is a list of function names whose string arguments should be ignored.
	// Supports direct calls (e.g., "println") and one-level qualified calls (e.g., "slog.Info").
	IgnoreFunctions []string
}

Config contains all configuration options for the goconst analyzer.

type ConstType

type ConstType struct {
	// Using embedded Position to save memory vs. a separate field
	token.Position
	// Interned strings to reduce memory usage
	Name string
	// contains filtered or unexported fields
}

ConstType holds information about a constant declaration.

func (ConstType) ValueKey added in v1.10.2

func (c ConstType) ValueKey() string

ValueKey returns the internal comparison key used to distinguish constants whose display values may be approximate, such as high-precision numbers.

type Constants

type Constants map[string][]ConstType

Constants maps string values to their constant definitions.

type ExtendedPos

type ExtendedPos struct {
	// Using embedded Position to save memory vs. a separate field
	token.Position
	// contains filtered or unexported fields
}

ExtendedPos extends token.Position with package information. This structure is optimized for memory usage in large codebases.

func GetExtendedPosBuffer added in v1.8.0

func GetExtendedPosBuffer() []ExtendedPos

GetExtendedPosBuffer retrieves an ExtendedPos slice from the pool

type Issue

type Issue struct {
	Pos              token.Position
	OccurrencesCount int
	Str              string
	MatchingConst    string
	DuplicateConst   string
	DuplicatePos     token.Position
}

Issue represents a finding of duplicated strings, numbers, or constants. Each Issue includes the position where it was found, how many times it occurs, the string itself, and any matching constant name. When both test and non-test files are analyzed, OccurrencesCount reflects the count within the issue's scope (test or non-test) rather than the global total.

func Run

func Run(files []*ast.File, fset *token.FileSet, typeInfo *types.Info, cfg *Config) ([]Issue, error)

Run analyzes the provided AST files for duplicated strings or numbers according to the provided configuration. It returns a slice of Issue objects containing the findings.

func RunWithConfig added in v1.8.0

func RunWithConfig(files []*ast.File, fset *token.FileSet, typeInfo *types.Info, cfg *Config) ([]Issue, error)

RunWithConfig is a convenience function that runs the analysis with a Config object directly supporting multiple ignore patterns.

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

Parser represents the core analysis engine for finding repeated strings and constants. It holds both configuration options and the internal state during analysis.

func New

func New(path, ignore, ignoreStrings string, ignoreTests, matchConstant, numbers, findDuplicates, evalConstExpressions bool, numberMin, numberMax, minLength, minOccurrences int, excludeTypes map[Type]bool) *Parser

New creates a new instance of the parser. This is your entry point if you'd like to use goconst as an API.

Parameters:

  • path: the file or directory path to analyze
  • ignore: regex pattern to ignore files
  • ignoreStrings: regex pattern to ignore strings
  • ignoreTests: whether to ignore test files
  • matchConstant: whether to match strings with existing constants
  • numbers: whether to analyze number literals
  • findDuplicates: whether to find consts with duplicate values
  • evalConstExpressions: whether to evaluate constant expressions
  • numberMin/numberMax: range limits for number analysis
  • minLength: minimum string length to consider
  • minOccurrences: minimum occurrences to report
  • excludeTypes: map of context types to exclude

func NewWithIgnorePatterns added in v1.8.0

func NewWithIgnorePatterns(
	path, ignore string,
	ignoreStrings []string,
	ignoreTests, matchConstant, numbers, findDuplicates, evalConstExpressions bool,
	numberMin, numberMax, minLength, minOccurrences int,
	excludeTypes map[Type]bool) *Parser

NewWithIgnorePatterns creates a new instance of the parser with support for multiple ignore patterns. This is an alternative constructor that takes a slice of ignore string patterns.

func (*Parser) EnableBatchProcessing added in v1.8.0

func (p *Parser) EnableBatchProcessing(batchSize int)

EnableBatchProcessing activates batch processing mode for very large codebases. This mode collects files in batches before processing them to reduce memory usage. The batchSize parameter controls how many files to process in each batch.

func (*Parser) GetStringCount added in v1.8.0

func (p *Parser) GetStringCount(str string) int

GetStringCount safely gets the count for a string

func (*Parser) IncrementStringCount added in v1.8.0

func (p *Parser) IncrementStringCount(str string) int

IncrementStringCount safely increments the count for a string and returns the new count

func (*Parser) ParseTree

func (p *Parser) ParseTree() (Strings, Constants, error)

ParseTree will search the given path for occurrences that could be moved into constants. If "..." is appended, the search will be recursive.

It returns maps of strings and constants found during the analysis, and any error encountered. Use ProcessResults to filter the results based on configuration before retrieving them.

func (*Parser) ProcessResults

func (p *Parser) ProcessResults()

ProcessResults post-processes the raw results. It filters the discovered strings based on the parser's configuration: - Removes strings that don't meet the minimum occurrences threshold - Filters out strings matching the ignore pattern - Applies number range filtering if min/max values are set

func (*Parser) SetConcurrency added in v1.8.0

func (p *Parser) SetConcurrency(max int)

SetConcurrency allows setting the maximum number of goroutines to use for parallel file processing. Default is the number of CPUs.

func (*Parser) SetIgnoreFunctions added in v1.10.0

func (p *Parser) SetIgnoreFunctions(names []string)

SetIgnoreFunctions configures which function calls should have their string arguments ignored. Supports direct calls (e.g., "println") and one-level qualified calls (e.g., "slog.Info", "fmt.Errorf").

type Strings

type Strings map[string][]ExtendedPos

Strings maps string literals to their positions in the code.

type Type

type Type int

Type represents the context in which a string literal appears.

const (
	// Assignment represents a string in an assignment context (e.g., x := "foo")
	Assignment Type = iota
	// Binary represents a string in a binary expression (e.g., x == "foo")
	Binary
	// Case represents a string in a case clause (e.g., case "foo":)
	Case
	// Return represents a string in a return statement (e.g., return "foo")
	Return
	// Call represents a string passed as an argument to a function call (e.g., f("foo"))
	Call
	// CompositeLit represents a string inside a composite literal
	// (e.g., []string{"foo"}, map[string]string{"k": "v"}, MyStruct{Field: "foo"})
	CompositeLit
)

Directories

Path Synopsis
cmd
goconst command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL