CLI tool for generating iterators that selects items by their field values.
go install github.com/miyamo2/filtgen@latest//go:generate filtgen generate -s $GOFILE
package main
import (
"time"
)
type Foo struct {
StringField string `filtgen:"*"`
IntField int `filtgen:"*"`
BoolField bool `filtgen:"*"`
TimeField time.Time `filtgen:"*"`
ErrorField error `filtgen:"*"`
}go generate ./...filtgen generate -s your_struct.goerrSomething := errors.New("something")
s := []Foo{
{StringField: "a", IntField: 1, BoolField: true, TimeField: time.Now()},
{StringField: "b", IntField: 2, BoolField: false, TimeField: time.Now(), ErrorField: errSomething},
{StringField: "c", IntField: 3, BoolField: true, TimeField: time.Now().Add(-(time.Hour * 2))},
}
for i, v := range FooSlice(s).StringFieldGe("a") {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 0: a
// 1: b
// 2: c
for i, v := range FooSlice(s).IntFieldGt(1) {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 1: b
// 2: c
for i, v := range FooSlice(s).BoolFieldEq(true) {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 0: a
// 2: c
for i, v := range FooSlice(s).TimeFieldMatches(func(t time.Time) bool { return t.Before(time.Now()) }) {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 2: c
for i, v := range FooSlice(s).ErrorFieldIs(errSomething) {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 1: b
// with method chaining
for i, v := range FooSlice(s).IntFieldGt(1).StringFieldNe("c") {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 1: bFor the actual generated code, see the example.
filtgen generates the following defined-types.
-
XxxSlice([]T) -
XxxMap[K](map[K compareble]T) -
XxxSeq[T](iter.Seq[T]) -
XxxSeq2[T](iter.Seq2[T, U])
Type name is determined by the struct name; e.g. User -> UserSlice.
To use the generated methods, cast must be performed.
s := []User{
{Name: "Alice"},
{Name: "Bob"},
}
for i, v := range UserSlice(s).NameEq("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}Following methods are generated by filtgen.
Method name is determined by the field name; e.g. Name -> NameEq.
Selects iterator items whose field values are equal to the specified value.
type User struct {
Name string `filtgen:"eq"`
}for i, v := range UserSlice(s).NameEq("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}Selects iterator items whose field values are not equal to the specified value.
type User struct {
Name string `filtgen:"ne"`
}for i, v := range UserSlice(s).NameNe("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}Selects iterator items whose field values are greater than the specified value.
type User struct {
Name string `filtgen:"gt"`
}for i, v := range UserSlice(s).NameGt("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}Selects iterator items whose field values are less than the specified value.
type User struct {
Name string `filtgen:"lt"`
}for i, v := range UserSlice(s).NameLt("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}Selects iterator items whose field values are greater than or equal to the specified value.
type User struct {
Name string `filtgen:"ge"`
}for i, v := range UserSlice(s).NameGe("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}Selects iterator items whose field values are less than or equal to the specified value.
type User struct {
Name string `filtgen:"le"`
}for i, v := range UserSlice(s).NameLe("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}Selects iterator items whose field values match the specified function.
type User struct {
Name string `filtgen:"matches"`
}for i, v := range UserSlice(s).NameMatches(func(s string) bool { return strings.HasPrefix(s, "A") }) {
fmt.Printf("%d: %s\n", i, v.Name)
}Selects iterator items whose field values are equal to the specified error.
Equivalence is determined by errors.Is.
type Transaction struct {
ID string `filtgen:"eq"`
Err error `filtgen:"is"`
}for i, v := range TransactionSlice(s).ErrIs(fmt.Errorf("something")) {
fmt.Printf("%d: %s\n", i, v.ID)
}Selects iterator items whose field values are not equal to the specified error.
Equivalence is determined by errors.Is.
type Transaction struct {
ID string `filtgen:"eq"`
Err error `filtgen:"isnt"`
}for i, v := range TransactionSlice(s).ErrIsnt(fmt.Errorf("something")) {
fmt.Printf("%d: %s\n", i, v.ID)
}| Type\Filter | XxxEq |
XxxNe |
XxxGt |
XxxLt |
XxxGe |
XxxLe |
XxxMatches |
XxxIs |
XxxIsnt |
|---|---|---|---|---|---|---|---|---|---|
string |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
int |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
int8 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
int16 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
int32 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
int64 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
uint |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
uint8 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
uint16 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
uint32 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
uint64 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
float32 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
float64 |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
complex64 |
❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
complex128 |
❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
byte |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
rune |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
error |
❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
bool |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| other-types | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
The following values can be set in the filtgen tag.
If you want to set multiple values, separate them with ,.
type A struct {
StringField string `filtgen:"eq,ne"`
}| Value | Description |
|---|---|
* |
Generate all methods supported according to the type of that field. |
eq |
Generate XxxEq methods. |
ne |
Generate XxxNe methods. |
gt |
Generate XxxGt methods. |
lt |
Generate XxxLt methods. |
ge |
Generate XxxGe methods. |
le |
Generate XxxLe methods. |
matches |
Generate XxxMatches methods. |
is |
Generate XxxIs methods. |
isnt |
Generate XxxIsnt methods. |
Feel free to open a PR or an Issue.
However, you must promise to follow our Code of Conduct.
We recommend that this section be run with xc.
Install golangci-lint.
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latestgolangci-lint run --fixfiltgen released under the MIT License