go-enum

An enum generator for go

How it works

go-enum will take a commented type declaration like this:

// ENUM(jpeg, jpg, png, tiff, gif)
type ImageType int

and generate a file with the iota definition along various optional niceties that you may need:

const (
 // ImageTypeJpeg is a ImageType of type Jpeg.
 ImageTypeJpeg ImageType = iota
 // ImageTypeJpg is a ImageType of type Jpg.
 ImageTypeJpg
 // ImageTypePng is a ImageType of type Png.
 ImageTypePng
 // ImageTypeTiff is a ImageType of type Tiff.
 ImageTypeTiff
 // ImageTypeGif is a ImageType of type Gif.
 ImageTypeGif
)

// String implements the Stringer interface.
func (x ImageType) String() string

// ParseImageType attempts to convert a string to a ImageType.
func ParseImageType(name string) (ImageType, error)

// MarshalText implements the text marshaller method.
func (x ImageType) MarshalText() ([]byte, error)

// UnmarshalText implements the text unmarshaller method.
func (x *ImageType) UnmarshalText(text []byte) error
MarshalTextUnmarshalText
-t

Now with string typed enums

// ENUM(pending, running, completed, failed)
type StrState string
const (
 // StrStatePending is a StrState of type pending.
 StrStatePending StrState = "pending"
 // StrStateRunning is a StrState of type running.
 StrStateRunning StrState = "running"
 // StrStateCompleted is a StrState of type completed.
 StrStateCompleted StrState = "completed"
 // StrStateFailed is a StrState of type failed.
 StrStateFailed StrState = "failed"
)
--sqlint
// swagger:enum StrState
// ENUM(pending, running, completed, failed)
type StrState string

Goal

type EnumName int
String()

Installation

You can now download a release directly from github and use that for generating your enums! (Thanks to GoReleaser)

uname -suname -m
    curl -fsSL "https://github.com/abice/go-enum/releases/download/$(GO_ENUM_VERSION)/go-enum_$(uname -s)_$(uname -m)" -o go-enum

Adding it to your project

Using go generate
//go:generate go-enum --marshalgo generate ./...
Using Makefile

If you prefer makefile stuff, you can always do something like this:

STANDARD_ENUMS = ./_example/animal_enum.go \
 ./_example/color_enum.go

NULLABLE_ENUMS = ./_example/sql_enum.go

$(STANDARD_ENUMS): GO_ENUM_FLAGS=--nocase --marshal --names --ptr
$(NULLABLE_ENUMS): GO_ENUM_FLAGS=--nocase --marshal --names --sqlnullint --ptr

enums: $(STANDARD_ENUMS) $(NULLABLE_ENUMS)

# The generator statement for go enum files.  Files that invalidate the
# enum file: source file, the binary itself, and this file (in case you want to generate with different flags)
%_enum.go: %.go $(GOENUM) Makefile
 $(GOENUM) -f $*.go $(GO_ENUM_FLAGS)

Command options

go-enum --help

NAME:
   go-enum - An enum generator for go

USAGE:
   go-enum [global options] [arguments...]

VERSION:
   example

GLOBAL OPTIONS:
   --file value, -f value [ --file value, -f value ]          The file(s) to generate enums.  Use more than one flag for more files. [$GOFILE]
   --noprefix                                                 Prevents the constants generated from having the Enum as a prefix. (default: false)
   --lower                                                    Adds lowercase variants of the enum strings for lookup. (default: false)
   --nocase                                                   Adds case insensitive parsing to the enumeration (forces lower flag). (default: false)
   --marshal                                                  Adds text (and inherently json) marshalling functions. (default: false)
   --sql                                                      Adds SQL database scan and value functions. (default: false)
   --sqlint                                                   Tells the generator that a string typed enum should be stored in sql as an integer value. (default: false)
   --flag                                                     Adds golang flag functions. (default: false)
   --prefix value                                             Adds a prefix with a user one. If you would like to replace the prefix, then combine this option with --noprefix.
   --names                                                    Generates a 'Names() []string' function, and adds the possible enum values in the error response during parsing (default: false)
   --values                                                   Generates a 'Values() []{{ENUM}}' function. (default: false)
   --nocamel                                                  Removes the snake_case to CamelCase name changing (default: false)
   --ptr                                                      Adds a pointer method to get a pointer from const values (default: false)
   --sqlnullint                                               Adds a Null{{ENUM}} type for marshalling a nullable int value to sql (default: false)
   --sqlnullstr                                               Adds a Null{{ENUM}} type for marshalling a nullable string value to sql.  If sqlnullint is specified too, it will be Null{{ENUM}}Str (default: false)
   --template value, -t value [ --template value, -t value ]  Additional template file(s) to generate enums.  Use more than one flag for more files. Templates will be executed in alphabetical order.
   --alias value, -a value [ --alias value, -a value ]        Adds or replaces aliases for a non alphanumeric value that needs to be accounted for. [Format should be "key:value,key2:value2", or specify multiple entries, or both!]
   --mustparse                                                Adds a Must version of the Parse that will panic on failure. (default: false)
   --forcelower                                               Forces a camel cased comment to generate lowercased names. (default: false)
   --forceupper                                               Forces a camel cased comment to generate uppercased names. (default: false)
   --nocomments                                               Removes auto generated comments.  If you add your own comments, these will still be created. (default: false)
   --buildtag value, -b value [ --buildtag value, -b value ]  Adds build tags to a generated enum file.
   --help, -h                                                 show help
   --version, -v                                              print the version
Syntax
ENUM()=numericValue5051, 52, 53...
Comments
//
// Commented is an enumeration of commented values
/*
ENUM(
value1 // Commented value 1
value2
value3 // Commented value 3
)
*/
type Commented int

The generated comments in code will look something like:

...
const (
    // CommentedValue1 is a Commented of type Value1
    // Commented value 1
    CommentedValue1 Commented = iota
    // CommentedValue2 is a Commented of type Value2
    CommentedValue2
    // CommentedValue3 is a Commented of type Value3
    // Commented value 3
    CommentedValue3
)
...
Example
_example
// Color is an enumeration of colors that are allowed.
/* ENUM(
Black, White, Red
Green = 33 // Green starts with 33
*/
// Blue
// grey=
// yellow
// blue-green
// red-orange
// yellow_green
// red-orange-blue
// )
type Color int32

The generated code will look something like:

// Code generated by go-enum DO NOT EDIT.
// Version: example
// Revision: example
// Build Date: example
// Built By: example

package example

import (
 "fmt"
 "strings"
)

const (
 // ColorBlack is a Color of type Black.
 ColorBlack Color = iota
 // ColorWhite is a Color of type White.
 ColorWhite
 // ColorRed is a Color of type Red.
 ColorRed
 // ColorGreen is a Color of type Green.
 // Green starts with 33
 ColorGreen Color = iota + 30
 // ColorBlue is a Color of type Blue.
 ColorBlue
 // ColorGrey is a Color of type Grey.
 ColorGrey
 // ColorYellow is a Color of type Yellow.
 ColorYellow
 // ColorBlueGreen is a Color of type Blue-Green.
 ColorBlueGreen
 // ColorRedOrange is a Color of type Red-Orange.
 ColorRedOrange
 // ColorYellowGreen is a Color of type Yellow_green.
 ColorYellowGreen
 // ColorRedOrangeBlue is a Color of type Red-Orange-Blue.
 ColorRedOrangeBlue
)

const _ColorName = "BlackWhiteRedGreenBluegreyyellowblue-greenred-orangeyellow_greenred-orange-blue"

var _ColorMap = map[Color]string{
 ColorBlack:         _ColorName[0:5],
 ColorWhite:         _ColorName[5:10],
 ColorRed:           _ColorName[10:13],
 ColorGreen:         _ColorName[13:18],
 ColorBlue:          _ColorName[18:22],
 ColorGrey:          _ColorName[22:26],
 ColorYellow:        _ColorName[26:32],
 ColorBlueGreen:     _ColorName[32:42],
 ColorRedOrange:     _ColorName[42:52],
 ColorYellowGreen:   _ColorName[52:64],
 ColorRedOrangeBlue: _ColorName[64:79],
}

// String implements the Stringer interface.
func (x Color) String() string {
 if str, ok := _ColorMap[x]; ok {
  return str
 }
 return fmt.Sprintf("Color(%d)", x)
}

var _ColorValue = map[string]Color{
 _ColorName[0:5]:                    ColorBlack,
 strings.ToLower(_ColorName[0:5]):   ColorBlack,
 _ColorName[5:10]:                   ColorWhite,
 strings.ToLower(_ColorName[5:10]):  ColorWhite,
 _ColorName[10:13]:                  ColorRed,
 strings.ToLower(_ColorName[10:13]): ColorRed,
 _ColorName[13:18]:                  ColorGreen,
 strings.ToLower(_ColorName[13:18]): ColorGreen,
 _ColorName[18:22]:                  ColorBlue,
 strings.ToLower(_ColorName[18:22]): ColorBlue,
 _ColorName[22:26]:                  ColorGrey,
 strings.ToLower(_ColorName[22:26]): ColorGrey,
 _ColorName[26:32]:                  ColorYellow,
 strings.ToLower(_ColorName[26:32]): ColorYellow,
 _ColorName[32:42]:                  ColorBlueGreen,
 strings.ToLower(_ColorName[32:42]): ColorBlueGreen,
 _ColorName[42:52]:                  ColorRedOrange,
 strings.ToLower(_ColorName[42:52]): ColorRedOrange,
 _ColorName[52:64]:                  ColorYellowGreen,
 strings.ToLower(_ColorName[52:64]): ColorYellowGreen,
 _ColorName[64:79]:                  ColorRedOrangeBlue,
 strings.ToLower(_ColorName[64:79]): ColorRedOrangeBlue,
}

// ParseColor attempts to convert a string to a Color
func ParseColor(name string) (Color, error) {
 if x, ok := _ColorValue[name]; ok {
  return x, nil
 }
 return Color(0), fmt.Errorf("%s is not a valid Color", name)
}

func (x Color) Ptr() *Color {
 return &x
}

// MarshalText implements the text marshaller method
func (x Color) MarshalText() ([]byte, error) {
 return []byte(x.String()), nil
}

// UnmarshalText implements the text unmarshaller method
func (x *Color) UnmarshalText(text []byte) error {
 name := string(text)
 tmp, err := ParseColor(name)
 if err != nil {
  return err
 }
 *x = tmp
 return nil
}