dmarkham/enumer

A Go tool to auto generate methods for your enums

Go

521

210 commits

updated Oct 3, 2026

See the code

README

Enumer

GoDoc GitHub Release

Enumer generates Go code that adds useful methods to enums (constants with a specific type).

Given this:

//go:generate go run github.com/dmarkham/enumer@latest -type=Pill -json
type Pill int

const (
	Placebo Pill = iota
	Aspirin
	Ibuprofen
	Paracetamol
	Acetaminophen = Paracetamol
)

go generate writes pill_enumer.go and you can do this:

fmt.Println(Aspirin)               // Aspirin
p, err := PillString("ibuprofen")  // p == Ibuprofen (case-insensitive)
PillValues()                       // [Placebo Aspirin Ibuprofen Paracetamol]
PillStrings()                      // [Placebo Aspirin Ibuprofen Paracetamol]
Pill(42).IsAPill()                 // false
json.Marshal(Aspirin)              // "Aspirin"

Enumer is a drop-in replacement for stringer. It generates the same String() method plus the extras below, so existing code keeps working.

Install

Enumer needs Go 1.25 or newer.

The recommended setup pins enumer in go.mod as a tool dependency, so go generate works on a fresh clone with no separate install:

go get -tool github.com/dmarkham/enumer@latest
//go:generate go tool enumer -type=Pill

examples/gomods is a runnable module set up this way.

Two other options:

# Run on demand from go:generate without touching go.mod.
//go:generate go run github.com/dmarkham/enumer@latest -type=Pill

# Install a binary on your PATH.
go install github.com/dmarkham/enumer@latest

Prebuilt binaries for Linux, macOS, and Windows are on the releases page.

Usage

enumer [flags] -type T [directory]
enumer [flags] -type T files...   # files must be in a single package

-type is required and takes a comma-separated list of type names. Everything else is optional. Output goes to <type>_enumer.go in the source directory, lowercased, unless you pass -output.

Always generated

NameWhat it does
func (i T) String() stringName of the value. Unknown values print as T(42).
func TString(s string) (T, error)Value from its name. Matches exact name first, then lowercase.
func TValues() []TAll values, in declaration order. Aliases are skipped.
func TStrings() []stringAll names, in declaration order.
func (i T) IsAT() boolTrue if the value is one of the declared constants.

Encoding flags

Each flag adds the methods for one encoding. Combine as many as you need.

FlagMethods addedInterface
-jsonMarshalJSON, UnmarshalJSONencoding/json
-textMarshalText, UnmarshalTextencoding
-yamlMarshalYAML, UnmarshalYAMLgopkg.in/yaml.v2 style, also accepted by yaml.v3
-sqlValue, Scandatabase/sql/driver
-gqlgenMarshalGQL, UnmarshalGQLgqlgen

All of them store the enum as its string name. Unmarshaling an unknown name returns an error.

Use -text if the enum is a map key you encode as JSON. Without it, encoding/json writes the numeric value as the key.

Scan accepts string, []byte, or any fmt.Stringer. A nil value leaves the receiver unchanged.

Other flags

FlagWhat it does
-valuesAdds Values() []string, which ent uses for enum fields.
-validateAdds Validate() error, which returns an error when the value is not a declared constant.
-flag.valueAdds Set(string) error so the type satisfies flag.Value.
-pflag.valueAdds Set and Type() string so the type satisfies pflag.Value. Type returns all names joined by |.
-typederrorsWraps conversion errors with enumerrs.ErrValueInvalid. See Typed errors.
-linecommentUses the constant's trailing line comment as its name.
-commentAdds a comment line to the top of the generated file. Repeatable.
-outputOutput file name.

Changing the string names

By default the string name is the Go identifier. Three flags adjust it, applied in this order:

  1. -trimprefix removes a prefix. Pass a comma-separated list to try several. Names without the prefix are left alone.
  2. -transform rewrites the case. See the table below.
  3. -addprefix prepends a string.

The result is what String() returns, what TString() accepts, and what every encoding uses.

Transforms

Given a constant named MyTypeValue:

-transformResult
noop (default)MyTypeValue
snakemy_type_value
snake-upperMY_TYPE_VALUE
kebabmy-type-value
kebab-upperMY-TYPE-VALUE
dotmy.type.value
dot-upperMY.TYPE.VALUE
whitespacemy type value
lowermytypevalue
upperMYTYPEVALUE
titleMyTypeValue (first letter uppercased, rest unchanged)
title-lowermyTypeValue (first letter lowercased, rest unchanged)
firstM
first-upperM
first-lowerm

Word splitting only works from CamelCase. snake_upper, kebab_upper, dot_upper, first_upper, and first_lower are accepted as aliases of the hyphenated names.

Line comments

With -linecomment, a constant's trailing comment replaces its name. Constants without one keep their identifier.

const (
	Monday Day = iota // lunes
	Tuesday
	Friday // viernes
)

Monday.String() returns lunes, Tuesday.String() returns Tuesday.

Typed errors

With -typederrors, TString(), Validate() and the unmarshal methods return an error that matches enumerrs.ErrValueInvalid under errors.Is. The message still names the bad input.

import "github.com/dmarkham/enumer/enumerrs"

p, err := PillString("Vitamin")
if errors.Is(err, enumerrs.ErrValueInvalid) {
	// "Vitamin does not belong to Pill values"
}

This makes github.com/dmarkham/enumer a runtime dependency of your module, since the generated code imports enumerrs.

Examples

Snake-case JSON for an API:

enumer -type=Status -json -transform=snake

Strip a Go-style prefix and store in a database:

enumer -type=Color -trimprefix=Color -sql -text

Several types at once with a custom file name:

enumer -type=Pill,Day -output=enums_gen.go

History

Enumer started as a fork of Rob Pike's stringer, was extended by Álvaro López Espinosa, and continues here. jsonenums inspired the JSON support.

code-generation
codegeneration
codegenerator
enum
enums
generator
golang

dmarkham/enumer

A Go tool to auto generate methods for your enums

Go

521

210 commits

updated Oct 3, 2026

See the code

README

Enumer

GoDoc GitHub Release

Enumer generates Go code that adds useful methods to enums (constants with a specific type).

Given this:

//go:generate go run github.com/dmarkham/enumer@latest -type=Pill -json
type Pill int

const (
	Placebo Pill = iota
	Aspirin
	Ibuprofen
	Paracetamol
	Acetaminophen = Paracetamol
)

go generate writes pill_enumer.go and you can do this:

fmt.Println(Aspirin)               // Aspirin
p, err := PillString("ibuprofen")  // p == Ibuprofen (case-insensitive)
PillValues()                       // [Placebo Aspirin Ibuprofen Paracetamol]
PillStrings()                      // [Placebo Aspirin Ibuprofen Paracetamol]
Pill(42).IsAPill()                 // false
json.Marshal(Aspirin)              // "Aspirin"

Enumer is a drop-in replacement for stringer. It generates the same String() method plus the extras below, so existing code keeps working.

Install

Enumer needs Go 1.25 or newer.

The recommended setup pins enumer in go.mod as a tool dependency, so go generate works on a fresh clone with no separate install:

go get -tool github.com/dmarkham/enumer@latest
//go:generate go tool enumer -type=Pill

examples/gomods is a runnable module set up this way.

Two other options:

# Run on demand from go:generate without touching go.mod.
//go:generate go run github.com/dmarkham/enumer@latest -type=Pill

# Install a binary on your PATH.
go install github.com/dmarkham/enumer@latest

Prebuilt binaries for Linux, macOS, and Windows are on the releases page.

Usage

enumer [flags] -type T [directory]
enumer [flags] -type T files...   # files must be in a single package

-type is required and takes a comma-separated list of type names. Everything else is optional. Output goes to <type>_enumer.go in the source directory, lowercased, unless you pass -output.

Always generated

NameWhat it does
func (i T) String() stringName of the value. Unknown values print as T(42).
func TString(s string) (T, error)Value from its name. Matches exact name first, then lowercase.
func TValues() []TAll values, in declaration order. Aliases are skipped.
func TStrings() []stringAll names, in declaration order.
func (i T) IsAT() boolTrue if the value is one of the declared constants.

Encoding flags

Each flag adds the methods for one encoding. Combine as many as you need.

FlagMethods addedInterface
-jsonMarshalJSON, UnmarshalJSONencoding/json
-textMarshalText, UnmarshalTextencoding
-yamlMarshalYAML, UnmarshalYAMLgopkg.in/yaml.v2 style, also accepted by yaml.v3
-sqlValue, Scandatabase/sql/driver
-gqlgenMarshalGQL, UnmarshalGQLgqlgen

All of them store the enum as its string name. Unmarshaling an unknown name returns an error.

Use -text if the enum is a map key you encode as JSON. Without it, encoding/json writes the numeric value as the key.

Scan accepts string, []byte, or any fmt.Stringer. A nil value leaves the receiver unchanged.

Other flags

FlagWhat it does
-valuesAdds Values() []string, which ent uses for enum fields.
-validateAdds Validate() error, which returns an error when the value is not a declared constant.
-flag.valueAdds Set(string) error so the type satisfies flag.Value.
-pflag.valueAdds Set and Type() string so the type satisfies pflag.Value. Type returns all names joined by |.
-typederrorsWraps conversion errors with enumerrs.ErrValueInvalid. See Typed errors.
-linecommentUses the constant's trailing line comment as its name.
-commentAdds a comment line to the top of the generated file. Repeatable.
-outputOutput file name.

Changing the string names

By default the string name is the Go identifier. Three flags adjust it, applied in this order:

  1. -trimprefix removes a prefix. Pass a comma-separated list to try several. Names without the prefix are left alone.
  2. -transform rewrites the case. See the table below.
  3. -addprefix prepends a string.

The result is what String() returns, what TString() accepts, and what every encoding uses.

Transforms

Given a constant named MyTypeValue:

-transformResult
noop (default)MyTypeValue
snakemy_type_value
snake-upperMY_TYPE_VALUE
kebabmy-type-value
kebab-upperMY-TYPE-VALUE
dotmy.type.value
dot-upperMY.TYPE.VALUE
whitespacemy type value
lowermytypevalue
upperMYTYPEVALUE
titleMyTypeValue (first letter uppercased, rest unchanged)
title-lowermyTypeValue (first letter lowercased, rest unchanged)
firstM
first-upperM
first-lowerm

Word splitting only works from CamelCase. snake_upper, kebab_upper, dot_upper, first_upper, and first_lower are accepted as aliases of the hyphenated names.

Line comments

With -linecomment, a constant's trailing comment replaces its name. Constants without one keep their identifier.

const (
	Monday Day = iota // lunes
	Tuesday
	Friday // viernes
)

Monday.String() returns lunes, Tuesday.String() returns Tuesday.

Typed errors

With -typederrors, TString(), Validate() and the unmarshal methods return an error that matches enumerrs.ErrValueInvalid under errors.Is. The message still names the bad input.

import "github.com/dmarkham/enumer/enumerrs"

p, err := PillString("Vitamin")
if errors.Is(err, enumerrs.ErrValueInvalid) {
	// "Vitamin does not belong to Pill values"
}

This makes github.com/dmarkham/enumer a runtime dependency of your module, since the generated code imports enumerrs.

Examples

Snake-case JSON for an API:

enumer -type=Status -json -transform=snake

Strip a Go-style prefix and store in a database:

enumer -type=Color -trimprefix=Color -sql -text

Several types at once with a custom file name:

enumer -type=Pill,Day -output=enums_gen.go

History

Enumer started as a fork of Rob Pike's stringer, was extended by Álvaro López Espinosa, and continues here. jsonenums inspired the JSON support.

code-generation
codegeneration
codegenerator
enum
enums
generator
golang

Project health

Overall

4.1/10

Maintained

10/10

Code review

3/10
OpenSSF Scorecard

Latest release

v1.7.2 · Oct 3, 2026

Releases this year

6

Significant stargazers

Alec Thomas

1,436 followers · starred Nov 2022

Sam Halliday

473 followers · starred Nov 2021

Sasha Melentyev

108 followers · starred Sep 2023

Terin Stock

455 followers · starred Mar 2025