|
1 | 1 | # go-struct-enum |
2 | | -A fully featured Golang struct based enums |
| 2 | + |
| 3 | + |
| 4 | +[](https://pkg.go.dev/github.com/FabienMht/go-struct-enum) |
| 5 | +[](https://goreportcard.com/report/github.com/FabienMht/go-struct-enum) |
| 6 | +[](https://sourcegraph.com/github.com/FabienMht/go-struct-enum) |
| 7 | +[](https://github.com/FabienMht/go-struct-enum/tags) |
| 8 | +[](https://github.com/FabienMht/go-struct-enum/graphs/contributors) |
| 9 | +[](./LICENSE) |
| 10 | + |
| 11 | +A fully featured Golang struct based enums. |
| 12 | +It provides a simple way to declare enums and use them in structs. |
| 13 | + |
| 14 | +**Enums are [harden](https://github.com/nikolaydubina/go-enum-example/tree/master) against:** |
| 15 | +- Arithmetics operations |
| 16 | +- Comparison operators except == and != |
| 17 | +- Implicit cast of [untyped constants](https://medium.com/golangspec/untyped-constants-in-go-2c69eb519b5b) (use the based type instead of the enum type) |
| 18 | + |
| 19 | +**An enum implements the following interfaces:** |
| 20 | +- `fmt.Stringer` |
| 21 | +- `json.Marshaler` |
| 22 | +- `json.Unmarshaler` |
| 23 | +- `sql.Scanner` |
| 24 | +- `driver.Valuer` |
| 25 | + |
| 26 | +## Install |
| 27 | + |
| 28 | +**Download it:** |
| 29 | + |
| 30 | +```bash |
| 31 | +$ go get github.com/FabienMht/go-struct-enum |
| 32 | +``` |
| 33 | + |
| 34 | +**Add the following import:** |
| 35 | + |
| 36 | +```go |
| 37 | +enum "github.com/FabienMht/go-struct-enum" |
| 38 | +``` |
| 39 | + |
| 40 | +## Usage |
| 41 | + |
| 42 | +### Basic |
| 43 | + |
| 44 | +Checkout the detailed example in the [documentation](https://pkg.go.dev/github.com/FabienMht/go-struct-enum#pkg-examples) for more information. |
| 45 | + |
| 46 | +**Declare enum values:** |
| 47 | + |
| 48 | +```go |
| 49 | +var ( |
| 50 | + // Define States |
| 51 | + TestStateUnknown = &TestState{enum.New("")} |
| 52 | + TestStatePassed = &TestState{enum.New("passed")} |
| 53 | + TestStateSkipped = &TestState{enum.New("skipped")} |
| 54 | + TestStateFailed = &TestState{enum.New("failed")} |
| 55 | + |
| 56 | + // Define the ordered list of states |
| 57 | + TestStates = []enum.Enummer[string]{ |
| 58 | + TestStateUnknown, |
| 59 | + TestStatePassed, |
| 60 | + TestStateSkipped, |
| 61 | + TestStateFailed, |
| 62 | + } |
| 63 | + |
| 64 | + // Define states parsers |
| 65 | + ParseTestState = enum.Parse(TestStates) |
| 66 | + MustParseTestState = enum.MustParse(TestStates) |
| 67 | +) |
| 68 | + |
| 69 | +// Define the state enum |
| 70 | +type TestState struct { |
| 71 | + enum.Enum[string] |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +**Use enum values:** |
| 76 | + |
| 77 | +```go |
| 78 | +// Parse a state |
| 79 | +state := ParseTestState("passed") // TestStatePassed |
| 80 | +// Or panic if the state is not valid |
| 81 | +state := MustParseTestState("passed") // TestStatePassed |
| 82 | + |
| 83 | +// Get the state value |
| 84 | +state.Value() // "passed" |
| 85 | +// Check the enum value |
| 86 | +state.EqualValue("passed") // true |
| 87 | +``` |
| 88 | + |
| 89 | +**Use enum in structs:** |
| 90 | + |
| 91 | +```go |
| 92 | +type Test struct { |
| 93 | + State *TestState `json:"state"` |
| 94 | +} |
| 95 | + |
| 96 | +// Marshal a struct with an enum |
| 97 | +json.Marshal(&Test{State: TestStatePassed}) // {"state":"passed"} |
| 98 | + |
| 99 | +// Unmarshal a struct with an enum |
| 100 | +var test Test |
| 101 | +json.Unmarshal([]byte(`{"state":"passed"}`), &test) // &Test{State: TestStatePassed} |
| 102 | +``` |
| 103 | + |
| 104 | +### Comparison |
| 105 | + |
| 106 | +Checkout the detailed example in the [documentation](https://pkg.go.dev/github.com/FabienMht/go-struct-enum#pkg-examples) for more information. |
| 107 | + |
| 108 | +**Define comparison functions:** |
| 109 | + |
| 110 | +```go |
| 111 | +// Define the state enum |
| 112 | +type TestState struct { |
| 113 | + enum.Enum[string] |
| 114 | +} |
| 115 | + |
| 116 | +func (ts *TestState) Equal(other *TestState) bool { |
| 117 | + return enum.Equal(ts, other) |
| 118 | +} |
| 119 | + |
| 120 | +func (ts *TestState) GreaterThan(other *TestState) bool { |
| 121 | + return enum.GreaterThan(TestStates)(ts, other) |
| 122 | +} |
| 123 | + |
| 124 | +func (ts *TestState) LessThan(other *TestState) bool { |
| 125 | + return enum.LessThan(TestStates)(ts, other) |
| 126 | +} |
| 127 | + |
| 128 | +func (ts *TestState) GreaterThanOrEqual(other *TestState) bool { |
| 129 | + return enum.GreaterThanOrEqual(TestStates)(ts, other) |
| 130 | +} |
| 131 | + |
| 132 | +func (ts *TestState) LessThanOrEqual(other *TestState) bool { |
| 133 | + return enum.LessThanOrEqual(TestStates)(ts, other) |
| 134 | +} |
| 135 | +``` |
| 136 | + |
| 137 | +**Use comparison functions:** |
| 138 | + |
| 139 | +```go |
| 140 | +TestStatePassed.Equal(TestStatePassed) // true |
| 141 | +TestStatePassed.Equal(TestStateFailed) // false |
| 142 | +TestStatePassed.GreaterThan(TestStatePassed) // false |
| 143 | +TestStatePassed.GreaterThan(TestStateFailed) // false |
| 144 | +TestStatePassed.GreaterThanOrEqual(TestStatePassed) // true |
| 145 | +TestStatePassed.GreaterThanOrEqual(TestStateFailed) // false |
| 146 | +TestStatePassed.LessThan(TestStatePassed) // false |
| 147 | +TestStatePassed.LessThan(TestStateFailed) // true |
| 148 | +TestStatePassed.LessThanOrEqual(TestStatePassed) // true |
| 149 | +TestStatePassed.LessThanOrEqual(TestStateFailed) // true |
| 150 | +``` |
| 151 | + |
| 152 | +## Benchmark |
| 153 | + |
| 154 | +```bash |
| 155 | +$ task bench |
| 156 | +task: [bench] go test -bench=. -benchmem |
| 157 | +goos: linux |
| 158 | +goarch: amd64 |
| 159 | +pkg: github.com/FabienMht/go-struct-enum |
| 160 | +cpu: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz |
| 161 | +BenchmarkParse-8 15764276 77.69 ns/op 48 B/op 1 allocs/op |
| 162 | +BenchmarkParsePrealloc-8 383380515 3.034 ns/op 0 B/op 0 allocs/op |
| 163 | +BenchmarkEqual-8 63047527 16.52 ns/op 0 B/op 0 allocs/op |
| 164 | +BenchmarkGreaterThan-8 6585123 187.9 ns/op 48 B/op 1 allocs/op |
| 165 | +BenchmarkGreaterThanPrealloc-8 10859983 108.9 ns/op 0 B/op 0 allocs/op |
| 166 | +BenchmarkGreaterThanOrEqual-8 6594724 184.5 ns/op 48 B/op 1 allocs/op |
| 167 | +BenchmarkGreaterThanOrEqualPrealloc-8 10677360 107.0 ns/op 0 B/op 0 allocs/op |
| 168 | +BenchmarkLessThan-8 6341217 183.0 ns/op 48 B/op 1 allocs/op |
| 169 | +BenchmarkLessThanPrealloc-8 10930384 107.0 ns/op 0 B/op 0 allocs/op |
| 170 | +BenchmarkLessThanOrEqualThan-8 6474268 182.1 ns/op 48 B/op 1 allocs/op |
| 171 | +BenchmarkLessThanOrEqualThanPrealloc-8 10892846 107.9 ns/op 0 B/op 0 allocs/op |
| 172 | +PASS |
| 173 | +ok github.com/FabienMht/go-struct-enum 14.543s |
| 174 | +``` |
| 175 | + |
| 176 | +## Contributing |
| 177 | + |
| 178 | +Contributions are welcome ! Please open an issue or submit a pull request. |
| 179 | + |
| 180 | +```bash |
| 181 | +# Install task |
| 182 | +$ go install github.com/go-task/task/v3/cmd/task@v3 |
| 183 | + |
| 184 | +# Install dev dependencies |
| 185 | +$ task dev |
| 186 | + |
| 187 | +# Run linter |
| 188 | +$ task lint |
| 189 | + |
| 190 | +# Run tests |
| 191 | +$ task test |
| 192 | + |
| 193 | +# Run benchmarks |
| 194 | +$ task bench |
| 195 | +``` |
0 commit comments