alvaroloes / enumer

A Go tool to auto generate methods for your enums
Other
478 stars 111 forks source link

Enumer GoDoc Go Report Card cover.run go

Enumer is a tool to generate Go code that adds useful methods to Go enums (constants with a specific type). It started as a fork of Rob Pike’s Stringer tool.

Install

Enumer can be installed as any other go command:

go get github.com/alvaroloes/enumer

After that, the enumer executable will be in "$GOPATH/bin" folder and you can use it with go generate

Generated functions and methods

When Enumer is applied to a type, it will generate:

For example, if we have an enum type called Pill,

type Pill int

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

executing enumer -type=Pill -json will generate a new file with four basic methods and two extra for JSON:

func (i Pill) String() string { 
    //...
}

func PillString(s string) (Pill, error) { 
    //...
}

func PillValues() []Pill { 
    //...
}

func (i Pill) IsAPill() bool { 
    //...
}

func (i Pill) MarshalJSON() ([]byte, error) {
    //...
}

func (i *Pill) UnmarshalJSON(data []byte) error {
    //...
}

From now on, we can:

// Convert any Pill value to string
var aspirinString string = Aspirin.String()
// (or use it in any place where a Stringer is accepted)
fmt.Println("I need ", Paracetamol) // Will print "I need Paracetamol"

// Convert a string with the enum name to the corresponding enum value
pill, err := PillString("Ibuprofen")
if err != nil {
    fmt.Println("Unrecognized pill: ", err)
    return
}
// Now pill == Ibuprofen

// Get all the values of the string
allPills := PillValues()
fmt.Println(allPills) // Will print [Placebo Aspirin Ibuprofen Paracetamol]

// Check if a value belongs to the Pill enum values
var notAPill Pill = 42
if (notAPill.IsAPill()) {
    fmt.Println(notAPill, "is not a value of the Pill enum")
}

// Marshal/unmarshal to/from json strings, either directly or automatically when
// the enum is a field of a struct
pillJSON := Aspirin.MarshalJSON()
// Now pillJSON == `"Aspirin"`

The generated code is exactly the same as the Stringer tool plus the mentioned additions, so you can use Enumer where you are already using Stringer without any code change.

Transforming the string representation of the enum value

By default, Enumer uses the same name of the enum value for generating the string representation (usually CamelCase in Go).

type MyType int

 ...

name := MyTypeValue.String() // name => "MyTypeValue"

Sometimes you need to use some other string representation format than CamelCase (i.e. in JSON).

To transform it from CamelCase to snake_case or kebab-case, you can use the transform flag.

For example, the command enumer -type=MyType -json -transform=snake would generate the following string representation:

name := MyTypeValue.String() // name => "my_type_value"

Note: The transformation only works form CamelCase to snake_case or kebab-case, not the other way around.

How to use

The usage of Enumer is the same as Stringer, so you can refer to the Stringer docs for more information.

There are four boolean flags: json, text, yaml and sql. You can use any combination of them (i.e. enumer -type=Pill -json -text),

For enum string representation transformation the transform and trimprefix flags were added (i.e. enumer -type=MyType -json -transform=snake). Possible transform values are snake and kebab for transformation to snake_case and kebab-case accordingly. The default value for transform flag is noop which means no transformation will be performed.

If a prefix is provided via the trimprefix flag, it will be trimmed from the start of each name (before it is transformed). If a name doesn't have the prefix it will be passed unchanged.

Inspiring projects