-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilter.go
57 lines (51 loc) · 1.3 KB
/
filter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package util
import (
"fmt"
"sync"
)
// StringFilterT is a tuple for a value that has not been filtered out
type StringFilterT struct {
String string
Err error
}
type StringFilterWrapper []StringFilterT
func (f StringFilterWrapper) Error() error {
var errs []error
for _, r := range f {
if r.Err != nil {
errs = append(errs, fmt.Errorf("'%s': %s", r.String, r.Err))
}
}
if len(errs) > 0 {
return fmt.Errorf("%v", errs)
}
return nil
}
// FilterFn is a function used to filter a list of string. If the
// function returns false or a non-nil error, it will not be filtered.
type FilterFn func(string) (filter bool, err error)
// StringFilter will run fn with each element of in, filtering out elements.
// it will return a slice of results where fn returned ok, or a non-nil error.
// it will also call each instance of fn in it's own goroutine.
func StringFilter(fn FilterFn, in ...string) StringFilterWrapper {
outCh := make(chan StringFilterT, len(in))
var wg sync.WaitGroup
for i, s := range in {
wg.Add(1)
go func(i int, s string) {
defer wg.Done()
if filter, err := fn(s); err != nil || !filter {
outCh <- StringFilterT{s, err}
}
}(i, s)
}
wg.Wait()
close(outCh)
res := make([]StringFilterT, len(outCh))
i := 0
for o := range outCh {
res[i] = o
i++
}
return res
}