Setting: enum
Definition
The Go language doesn't explicit define enums. In the context of Goverter an enum type is defined as a named type with an underlying type of (float
, string
, or integer
) having at least one constant defined in the same package.
enum
enum [yes|no]
can be defined as CLI argument or conversion comment. enum
is enabled per default.
enum
allows you to disable enum support in goverter.
Example (click me)
package example
import (
"time"
)
// goverter:converter
// goverter:enum no
type Converter interface {
Convert(MyDuration) time.Duration
}
type MyDuration int64
const (
Nanoseconds MyDuration = 1
Microseconds MyDuration = 1000 * Nanoseconds
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
disable "github.com/jmattheis/goverter/example/enum/disable"
"time"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source disable.MyDuration) time.Duration {
return time.Duration(source)
}
enum:unknown ACTION
enum:unknown ACTION|KEY
can be defined as CLI argument, conversion comment or method comment. This setting is inheritable.
Define what happens on an invalid or unexpected enum value.
enum:unknown @error
returns an error in the default case of the switch statement.
Example (click me)
package example
import (
"github.com/jmattheis/goverter/example/enum/unknown/input"
"github.com/jmattheis/goverter/example/enum/unknown/output"
)
// goverter:converter
// goverter:enum:unknown @error
type Converter interface {
Convert(input.Color) (output.Color, error)
}
package input
type Color int
const (
Green Color = iota
Blue
Red
)
package output
type Color string
const (
Green Color = "green"
Blue Color = "blue"
Red Color = "red"
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
"fmt"
input "github.com/jmattheis/goverter/example/enum/unknown/input"
output "github.com/jmattheis/goverter/example/enum/unknown/output"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source input.Color) (output.Color, error) {
var outputColor output.Color
switch source {
case input.Blue:
outputColor = output.Blue
case input.Green:
outputColor = output.Green
case input.Red:
outputColor = output.Red
default:
return outputColor, fmt.Errorf("unexpected enum element: %v", source)
}
return outputColor, nil
}
enum:unknown @ignore
does nothing in the default case of the switch statement.
Example (click me)
package example
import (
"github.com/jmattheis/goverter/example/enum/unknown/input"
"github.com/jmattheis/goverter/example/enum/unknown/output"
)
// goverter:converter
// goverter:enum:unknown @ignore
type Converter interface {
Convert(input.Color) output.Color
}
package input
type Color int
const (
Green Color = iota
Blue
Red
)
package output
type Color string
const (
Green Color = "green"
Blue Color = "blue"
Red Color = "red"
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
input "github.com/jmattheis/goverter/example/enum/unknown/input"
output "github.com/jmattheis/goverter/example/enum/unknown/output"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source input.Color) output.Color {
var outputColor output.Color
switch source {
case input.Blue:
outputColor = output.Blue
case input.Green:
outputColor = output.Green
case input.Red:
outputColor = output.Red
default: // ignored
}
return outputColor
}
enum:unknown @panic
panics in the default case of the switch statement.
Example (click me)
package example
import (
"github.com/jmattheis/goverter/example/enum/unknown/input"
"github.com/jmattheis/goverter/example/enum/unknown/output"
)
// goverter:converter
// goverter:enum:unknown @panic
type Converter interface {
Convert(input.Color) output.Color
}
package input
type Color int
const (
Green Color = iota
Blue
Red
)
package output
type Color string
const (
Green Color = "green"
Blue Color = "blue"
Red Color = "red"
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
"fmt"
input "github.com/jmattheis/goverter/example/enum/unknown/input"
output "github.com/jmattheis/goverter/example/enum/unknown/output"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source input.Color) output.Color {
var outputColor output.Color
switch source {
case input.Blue:
outputColor = output.Blue
case input.Green:
outputColor = output.Green
case input.Red:
outputColor = output.Red
default:
panic(fmt.Sprintf("unexpected enum element: %v", source))
}
return outputColor
}
enum:unknown KEY
: use an enum key in the default case of the switch statement
Example (click me)
package example
import (
"github.com/jmattheis/goverter/example/enum/unknown/key/input"
"github.com/jmattheis/goverter/example/enum/unknown/key/output"
)
// goverter:converter
type Converter interface {
// goverter:enum:unknown Unknown
Convert(input.Color) output.Color
}
package input
type Color int
const (
Green Color = iota
Blue
)
package output
type Color string
const (
Unknown Color = "unknown"
Green Color = "green"
Blue Color = "blue"
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
input "github.com/jmattheis/goverter/example/enum/unknown/key/input"
output "github.com/jmattheis/goverter/example/enum/unknown/key/output"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source input.Color) output.Color {
var outputColor output.Color
switch source {
case input.Blue:
outputColor = output.Blue
case input.Green:
outputColor = output.Green
default:
outputColor = output.Unknown
}
return outputColor
}
enum:exclude
enum:exclude [PACKAGE:]NAME
can be defined as CLI argument or conversion comment.
You can exclude falsely detected enums with exclude. This is useful when a type qualifies as enum but isn't one. If PACKAGE
is unset, goverter will use the package of the converter interface.
Both PACKAGE
and NAME
can be regular expressions.
Example (click me)
package example
import (
"time"
)
// goverter:converter
// goverter:enum:unknown @panic
// goverter:enum:exclude MyDuration
// goverter:enum:exclude time:Duration
type Converter interface {
Convert(MyDuration) time.Duration
}
type MyDuration int64
const (
Nanoseconds MyDuration = 1
Microseconds MyDuration = 1000 * Nanoseconds
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
exclude "github.com/jmattheis/goverter/example/enum/exclude"
"time"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source exclude.MyDuration) time.Duration {
return time.Duration(source)
}
enum:map SOURCE TARGET
enum:map SOURCE TARGET
can be defined as method comment.
enum:map
can be used to map an enum key of the source enum type to the target type. In this example we have two spellings of Gray|Grey.
Example (click me)
package example
import (
"github.com/jmattheis/goverter/example/enum/map/input"
"github.com/jmattheis/goverter/example/enum/map/output"
)
// goverter:converter
// goverter:enum:unknown @panic
type Converter interface {
// goverter:enum:map Gray Grey
Convert(input.Color) output.Color
}
package input
type Color int
const (
Green Color = 1
Gray Color = 3
)
package output
type Color string
const (
Green Color = "green"
Grey Color = "Grey"
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
"fmt"
input "github.com/jmattheis/goverter/example/enum/map/input"
output "github.com/jmattheis/goverter/example/enum/map/output"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source input.Color) output.Color {
var outputColor output.Color
switch source {
case input.Gray:
outputColor = output.Grey
case input.Green:
outputColor = output.Green
default:
panic(fmt.Sprintf("unexpected enum element: %v", source))
}
return outputColor
}
You can also use any of the @actions
from enum:unknown
. E.g.
Example (click me)
package example
import (
"github.com/jmattheis/goverter/example/enum/map-panic/input"
"github.com/jmattheis/goverter/example/enum/map-panic/output"
)
// goverter:converter
// goverter:enum:unknown @panic
type Converter interface {
// goverter:enum:map Gray @panic
Convert(input.Color) output.Color
}
package input
type Color int
const (
Green Color = 1
Gray Color = 3
)
package output
type Color string
const (
Green Color = "green"
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
"fmt"
input "github.com/jmattheis/goverter/example/enum/map-panic/input"
output "github.com/jmattheis/goverter/example/enum/map-panic/output"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source input.Color) output.Color {
var outputColor output.Color
switch source {
case input.Gray:
panic(fmt.Sprintf("unexpected enum element: %v", source))
case input.Green:
outputColor = output.Green
default:
panic(fmt.Sprintf("unexpected enum element: %v", source))
}
return outputColor
}
enum:transform ID [CONFIG]
enum:transform ID [CONFIG]
can be defined as method comment.
enum:transform
allows you to transform multiple enum keys to the target keys. There is currently one builtin transformers, but you can define transformers yourself.
enum:transform regex SEARCH REPLACE
With regex
you can do search and replace with regex of the enum keys.
Example (click me)
package example
// goverter:converter
// goverter:enum:unknown @panic
type Converter interface {
// goverter:enum:transform regex Col(\w+) ${1}Color
Convert(InputColor) OutputColor
// goverter:enum:transform regex (\w+)Color Col${1}
Convert2(OutputColor) InputColor
}
type InputColor int
const (
ColGreen InputColor = iota
ColBlue
ColRed
)
type OutputColor string
const (
GreenColor OutputColor = "green"
BlueColor OutputColor = "blue"
RedColor OutputColor = "red"
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
"fmt"
transformregex "github.com/jmattheis/goverter/example/enum/transform-regex"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source transformregex.InputColor) transformregex.OutputColor {
var exampleOutputColor transformregex.OutputColor
switch source {
case transformregex.ColBlue:
exampleOutputColor = transformregex.BlueColor
case transformregex.ColGreen:
exampleOutputColor = transformregex.GreenColor
case transformregex.ColRed:
exampleOutputColor = transformregex.RedColor
default:
panic(fmt.Sprintf("unexpected enum element: %v", source))
}
return exampleOutputColor
}
func (c *ConverterImpl) Convert2(source transformregex.OutputColor) transformregex.InputColor {
var exampleInputColor transformregex.InputColor
switch source {
case transformregex.BlueColor:
exampleInputColor = transformregex.ColBlue
case transformregex.GreenColor:
exampleInputColor = transformregex.ColGreen
case transformregex.RedColor:
exampleInputColor = transformregex.ColRed
default:
panic(fmt.Sprintf("unexpected enum element: %v", source))
}
return exampleInputColor
}
enum:transform CUSTOM
You can define a custom transformer by adding goverter as dependency to your project and then creating a new main
package in your project for your customized goverter. E.g. ./goverter/run.go
. Afterwards, you have to pass your custom enum transformer to cmd.Run
and then you can execute it via go run ./goverter
(use the package where you created you customized goverter). Here is an example that adds a trim-prefix transformer.
Example (click me)
package main
import (
"os"
"strings"
"github.com/jmattheis/goverter/cli"
"github.com/jmattheis/goverter/enum"
)
func main() {
opts := cli.RunOpts{
EnumTransformers: map[string]enum.Transformer{
"trim-prefix": trimPrefix,
},
}
cli.Run(os.Args, opts)
}
func trimPrefix(ctx enum.TransformContext) (map[string]string, error) {
m := map[string]string{}
for key := range ctx.Source.Members {
targetKey := strings.TrimPrefix(key, ctx.Config)
if _, ok := ctx.Target.Members[targetKey]; ok {
m[key] = targetKey
}
}
return m, nil
}
package example
// goverter:converter
// goverter:enum:unknown @panic
type Converter interface {
// goverter:enum:transform trim-prefix Color
Convert(InputColor) OutputColor
}
type InputColor int
const (
ColorGreen InputColor = iota
ColorBlue
ColorRed
)
type OutputColor string
const (
Green OutputColor = "green"
Blue OutputColor = "blue"
Red OutputColor = "red"
)
// Code generated by github.com/jmattheis/goverter, DO NOT EDIT.
//go:build !goverter
package generated
import (
"fmt"
example "goverter/example"
)
type ConverterImpl struct{}
func (c *ConverterImpl) Convert(source example.InputColor) example.OutputColor {
var exampleOutputColor example.OutputColor
switch source {
case example.ColorBlue:
exampleOutputColor = example.Blue
case example.ColorGreen:
exampleOutputColor = example.Green
case example.ColorRed:
exampleOutputColor = example.Red
default:
panic(fmt.Sprintf("unexpected enum element: %v", source))
}
return exampleOutputColor
}
Regex Implementation (click me)
package enum
import (
"fmt"
"regexp"
"strings"
)
var DefaultTransformers = map[string]Transformer{
"regex": transformRegex,
}
func transformRegex(ctx TransformContext) (map[string]string, error) {
parts := strings.Split(ctx.Config, " ")
if len(parts) != 2 {
return nil, fmt.Errorf("invalid config, expected two strings separated by space")
}
pattern, err := regexp.Compile(parts[0])
if err != nil {
return nil, fmt.Errorf("invalid pattern %q: %w", parts[0], err)
}
m := map[string]string{}
for key := range ctx.Source.Members {
targetKey := pattern.ReplaceAllString(key, parts[1])
if _, ok := ctx.Target.Members[targetKey]; ok {
m[key] = targetKey
}
}
return m, nil
}