Documentation
¶
Overview ¶
Package chans は、チャネルに関するユーティリティが配置されています。
Index ¶
- func Bridge[T any](done <-chan struct{}, chanCh <-chan <-chan T) <-chan T
- func BridgeContext[T any](ctx context.Context, chanCh <-chan <-chan T) <-chan T
- func Buffer[T any](done <-chan struct{}, in <-chan T, count int) <-chan []T
- func BufferContext[T any](ctx context.Context, in <-chan T, count int) <-chan []T
- func Chain(done, base <-chan struct{}, next func(finished time.Time)) <-chan struct{}
- func ChainContext(ctx context.Context, base context.Context, next func(finished time.Time)) context.Context
- func Chunk[T any](done <-chan struct{}, in <-chan T, count int) <-chan []T
- func ChunkContext[T any](ctx context.Context, in <-chan T, count int) <-chan []T
- func Concat[T any](done <-chan struct{}, channels ...<-chan T) <-chan T
- func ConcatContext[T any](ctx context.Context, channels ...<-chan T) <-chan T
- func Convert[F any, T any](done <-chan struct{}, in <-chan F, fn func(F) T) <-chan T
- func ConvertContext[F any, T any](ctx context.Context, in <-chan F, fn func(F) T) <-chan T
- func Enumerate[T any](done <-chan struct{}, in <-chan T) <-chan *IterValue[T]
- func EnumerateContext[T any](ctx context.Context, in <-chan T) <-chan *IterValue[T]
- func FanIn[T any](done <-chan struct{}, channels ...<-chan T) <-chan T
- func FanInContext[T any](ctx context.Context, channels ...<-chan T) <-chan T
- func FanOut[T any](done <-chan struct{}, in <-chan T, workerCount int, callback func(T)) []<-chan struct{}
- func FanOutContext[T any](ctx context.Context, in <-chan T, workerCount int, callback func(T)) []context.Context
- func FanOutWg[T any](done <-chan struct{}, in <-chan T, workerCount int, callback func(T)) *sync.WaitGroup
- func FanOutWgContext[T any](ctx context.Context, in <-chan T, workerCount int, callback func(T)) *sync.WaitGroup
- func Filter[T any](done <-chan struct{}, in <-chan T, predicate func(T) bool) <-chan T
- func FilterContext[T any](ctx context.Context, in <-chan T, predicate func(T) bool) <-chan T
- func ForEach[T any](done <-chan struct{}, in <-chan T, callback func(v T))
- func ForEachContext[T any](ctx context.Context, in <-chan T, callback func(v T))
- func FromIntCh(ch <-chan int) <-chan any
- func FromStringCh(ch <-chan string) <-chan any
- func Generator[T any](done <-chan struct{}, in ...T) <-chan T
- func GeneratorContext[T any](ctx context.Context, in ...T) <-chan T
- func Interval[T any](done <-chan struct{}, in <-chan T, interval time.Duration) <-chan T
- func IntervalContext[T any](ctx context.Context, in <-chan T, interval time.Duration) <-chan T
- func Loop(done <-chan struct{}, start, end int) <-chan int
- func LoopContext(ctx context.Context, start, end int) <-chan int
- func LoopInfinite(done <-chan struct{}) <-chan int
- func LoopInfiniteContext(ctx context.Context) <-chan int
- func Map[T any, R any](done <-chan struct{}, in <-chan T, fn MapFunc[T, R]) <-chan *MapValue[T, R]
- func MapContext[T any, R any](ctx context.Context, in <-chan T, fn MapFunc[T, R]) <-chan *MapValue[T, R]
- func Merge[T any](done <-chan struct{}, channels ...<-chan T) <-chan T
- func MergeContext[T any](ctx context.Context, channels ...<-chan T) <-chan T
- func OrDone[T any](done <-chan struct{}, in <-chan T) <-chan T
- func OrDoneContext[T any](ctx context.Context, in <-chan T) <-chan T
- func RecvAny(chs ...chan any) (chosen int, v any, ok bool)
- func Repeat[T any](done <-chan struct{}, values ...T) <-chan T
- func RepeatContext[T any](ctx context.Context, values ...T) <-chan T
- func RepeatFn[T any](done <-chan struct{}, fn func() T) <-chan T
- func RepeatFnContext[T any](ctx context.Context, fn func() T) <-chan T
- func Select(chs ...chan any) (chosen int, v any, ok bool)
- func Skip[T any](done <-chan struct{}, in <-chan T, count int) <-chan T
- func SkipContext[T any](ctx context.Context, in <-chan T, count int) <-chan T
- func SkipWhile[T comparable](done <-chan struct{}, in <-chan T, value T) <-chan T
- func SkipWhileContext[T comparable](ctx context.Context, in <-chan T, value T) <-chan T
- func SkipWhileFn[T comparable](done <-chan struct{}, in <-chan T, fn func() T) <-chan T
- func SkipWhileFnContext[T comparable](ctx context.Context, in <-chan T, fn func() T) <-chan T
- func Slice[T any](done <-chan struct{}, in <-chan T) []T
- func SliceContext[T any](ctx context.Context, in <-chan T) []T
- func Take[T any](done <-chan struct{}, in <-chan T, count int) <-chan T
- func TakeContext[T any](ctx context.Context, in <-chan T, count int) <-chan T
- func TakeWhile[T comparable](done <-chan struct{}, in <-chan T, value T) <-chan T
- func TakeWhileContext[T comparable](ctx context.Context, in <-chan T, value T) <-chan T
- func TakeWhileFn[T comparable](done <-chan struct{}, in <-chan T, fn func() T) <-chan T
- func TakeWhileFnContext[T comparable](ctx context.Context, in <-chan T, fn func() T) <-chan T
- func Tee[T any](done <-chan struct{}, in <-chan T) (<-chan T, <-chan T)
- func TeeContext[T any](ctx context.Context, in <-chan T) (<-chan T, <-chan T)
- func ToInt[T any](done <-chan struct{}, in <-chan T, failedValue int) <-chan int
- func ToString[T any](done <-chan struct{}, in <-chan T, failedValue string) <-chan string
- func WhenAll(channels ...<-chan struct{}) <-chan struct{}
- func WhenAllContext(pCtx context.Context, channels ...<-chan struct{}) context.Context
- func WhenAny(channels ...<-chan struct{}) <-chan struct{}
- func WhenAnyContext(pCtx context.Context, channels ...<-chan struct{}) context.Context
- type IterValue
- type MapFunc
- type MapValue
- type SelectValue
Examples ¶
- Bridge
- Buffer
- Chain
- Chunk
- Concat
- Convert
- Enumerate
- FanIn
- FanOut
- FanOutWg
- Filter
- ForEach
- FromIntCh
- FromStringCh
- Generator
- Interval
- Loop
- LoopInfinite
- Map
- Merge
- OrDone
- RecvAll
- RecvAny
- Repeat
- RepeatFn
- Select
- Skip
- SkipWhile
- SkipWhileFn
- SliceContext
- Take
- TakeWhile
- TakeWhileFn
- Tee
- ToInt
- ToString
- WhenAll
- WhenAny
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Bridge ¶ added in v0.1.5
func Bridge[T any](done <-chan struct{}, chanCh <-chan <-chan T) <-chan T
Bridge -- 指定されたチャネルのシーケンスを順に消費していく単一のチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
chSeq := make(chan (<-chan int))
go func() {
defer close(chSeq)
chSeq <- chans.GeneratorContext(procCtx, 1, 2, 3)
chSeq <- chans.GeneratorContext(procCtx, 4, 5, 6)
}()
for v := range chans.BridgeContext(procCtx, chSeq) {
fmt.Println(v)
}
}
Output: 1 2 3 4 5 6
func BridgeContext ¶ added in v0.5.3
BridgeContext-- Bridge の context.Context 版です。
func Buffer ¶ added in v0.2.18
Buffer は、入力を指定した件数分に束ねてデータを返すチャネルを生成します.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
data = []interface{}{1, 2, 3, 4, 5, 6, 7}
count = 3
)
numbers := chans.GeneratorContext(procCtx, data...)
chunks := chans.BufferContext(procCtx, numbers, count)
for chunk := range chunks {
fmt.Println(chunk)
}
}
Output: [1 2 3] [4 5 6] [7]
func BufferContext ¶ added in v0.5.3
BufferContext は、Bridge の context.Context 版です.
func Chain ¶ added in v0.2.14
Chain -- 指定された base チャネルがクローズした後に next で指定された関数を呼び出します.
done チャネルがクローズした場合、 next は実行されません。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
"github.com/devlights/gomy/ctxs"
)
func main() {
// context and channels
var (
ctx = context.Background()
base = func(pCtx context.Context) context.Context {
ctx, cxl := context.WithCancel(pCtx)
go func() {
defer cxl()
time.Sleep(100 * time.Millisecond)
fmt.Println("base")
}()
return ctx
}(ctx)
)
chain1 := chans.ChainContext(ctx, base, func(t time.Time) {
fmt.Println("chain-1")
})
chain2 := chans.ChainContext(ctx, chain1, func(t time.Time) {
fmt.Println("chain-2")
})
<-ctxs.WhenAll(ctx, base, chain1, chain2).Done()
}
Output: base chain-1 chain-2
func ChainContext ¶ added in v0.5.3
func ChainContext(ctx context.Context, base context.Context, next func(finished time.Time)) context.Context
ChainContext -- Chain の context.Context 版です.
func Chunk ¶ added in v0.3.0
Chunkは、入力を指定した件数分に束ねてデータを返すチャネルを生成します.
Buffer関数のエイリアスです。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 1, 2, 3, 4, 5, 6, 7)
chunks := chans.ChunkContext(procCtx, numbers, 3)
for chunk := range chunks {
fmt.Println(chunk)
}
}
Output: [1 2 3] [4 5 6] [7]
func ChunkContext ¶ added in v0.5.3
ChunkContext は、Chunk の context.Context 版です.
func Concat ¶ added in v0.1.7
func Concat[T any](done <-chan struct{}, channels ...<-chan T) <-chan T
Concat は、指定されたチャネルのシーケンスを順に消費していく単一のチャネルを返します.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
nums1 := chans.GeneratorContext(procCtx, 1, 2, 3)
nums2 := chans.GeneratorContext(procCtx, 4, 5, 6)
for v := range chans.ConcatContext(procCtx, nums1, nums2) {
fmt.Println(v)
}
}
Output: 1 2 3 4 5 6
func ConcatContext ¶ added in v0.5.3
ConcatContext は、 Concat の context.Context 版です.
func Convert ¶ added in v0.4.2
Convert は、入力用チャネルから値を取得し変換するチャネルを返します.
Example ¶
package main
import (
"context"
"fmt"
"strconv"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
numbers = chans.GeneratorContext(procCtx, 1, 2, 3)
converted = chans.ConvertContext(procCtx, numbers, func(v int) string { return strconv.Itoa(v) })
)
for v := range converted {
fmt.Printf("[%T]%q\n", v, v)
}
}
Output: [string]"1" [string]"2" [string]"3"
func ConvertContext ¶ added in v0.5.3
ConvertContext は、 Convert の context.Context 版です.
func Enumerate ¶ added in v0.2.0
Enumerate -- 指定された入力チャネルの要素に対してインデックスを付与したデータを返すチャネルを生成します。
戻り値のチャネルから取得できるデータ型は、*chans.IterValue となっています。
for v := range chans.Enumerate(done, inCh) {
// v.Index でインデックス、 v.Value で値が取得できる
}
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 9, 8, 7)
values := chans.EnumerateContext(procCtx, numbers)
for v := range values {
fmt.Printf("%d:%v\n", v.Index, v.Value)
}
}
Output: 0:9 1:8 2:7
func EnumerateContext ¶ added in v0.5.3
EnumerateContext は、 Enumerate の context.Context 版です.
func FanIn ¶ added in v0.1.5
func FanIn[T any](done <-chan struct{}, channels ...<-chan T) <-chan T
FanIn -- 指定されたチャネルリストをファンインするチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numStream1 := chans.GeneratorContext(procCtx, 1, 2, 3)
numStream2 := chans.GeneratorContext(procCtx, 4, 5, 6)
for v := range chans.FanInContext(procCtx, numStream1, numStream2) {
fmt.Println(v)
}
}
Output: 4 1 5 2 3 6
func FanInContext ¶ added in v0.5.3
FanInContext は、 FanIn の context.Context 版です.
func FanOut ¶ added in v0.2.1
func FanOut[T any](done <-chan struct{}, in <-chan T, workerCount int, callback func(T)) []<-chan struct{}
FanOut -- 指定されたチャネルの処理を指定されたワーカーの数でファンアウトします。
チャネルからデータを取得するたびに引数 callback が呼ばれます。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
"github.com/devlights/gomy/ctxs"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
nums = chans.GeneratorContext(procCtx, 1, 2, 3, 4, 5, 6)
callback = func(v int) { fmt.Println(v) }
)
dones := chans.FanOutContext(procCtx, nums, 3, callback)
<-ctxs.WhenAll(procCtx, dones...).Done()
}
Output: 4 1 2 3 6 5
func FanOutContext ¶ added in v0.5.3
func FanOutContext[T any](ctx context.Context, in <-chan T, workerCount int, callback func(T)) []context.Context
FanOutContext は、 Fanout の ctx.Context 版です.
func FanOutWg ¶ added in v0.2.2
func FanOutWg[T any](done <-chan struct{}, in <-chan T, workerCount int, callback func(T)) *sync.WaitGroup
FanOutWg -- FanOut() の sync.WaitGroup を返す版です。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
nums = chans.GeneratorContext(procCtx, 1, 2, 3, 4, 5, 6)
callback = func(v int) { fmt.Println(v) }
)
wg := chans.FanOutWgContext(procCtx, nums, 3, callback)
wg.Wait()
}
Output: 4 1 2 3 6 5
func FanOutWgContext ¶ added in v0.5.3
func FanOutWgContext[T any](ctx context.Context, in <-chan T, workerCount int, callback func(T)) *sync.WaitGroup
FanOutWgContext は、FanOutWg の context.Context 版です.
func Filter ¶ added in v0.2.0
Filter -- 入力データチャネル in から取得したデータを predicate に渡して 真(true) となったデータを返すチャネルを生成します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
numbers = chans.GeneratorContext(procCtx, 1, 2, 3, 4, 5)
predicate = func(v int) bool {
return v%2 == 0
}
)
for v := range chans.FilterContext(procCtx, numbers, predicate) {
fmt.Println(v)
}
}
Output: 2 4
func FilterContext ¶ added in v0.5.3
FilterContext は、Filter の context.Context 版です.
func ForEach ¶ added in v0.2.0
func ForEach[T any](done <-chan struct{}, in <-chan T, callback func(v T))
ForEach -- 指定されたチャネルをループします。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
in = chans.GeneratorContext(procCtx, 1, 2, 3)
)
chans.ForEachContext(procCtx, in, func(v int) {
fmt.Println(v)
})
}
Output: 1 2 3
func ForEachContext ¶ added in v0.5.3
ForEachContext は、ForEach の context.Context 版です.
func FromIntCh ¶ added in v0.2.0
FromIntCh -- chan int を chan any に変換します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var ints <-chan int = func(pCtx context.Context) <-chan int {
ctx, cxl := context.WithCancel(pCtx)
ch := make(chan int)
go func() {
defer cxl()
defer close(ch)
for i := 0; i < 3; i++ {
select {
case <-ctx.Done():
return
case ch <- i:
}
}
}()
return ch
}(procCtx)
var items <-chan interface{} = chans.FromIntCh(ints)
for v := range items {
fmt.Println(v)
}
}
Output: 0 1 2
func FromStringCh ¶ added in v0.2.0
FromStringCh -- chan string を chan any に変換します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var strs <-chan string = func(pCtx context.Context) <-chan string {
ctx, cxl := context.WithCancel(pCtx)
ch := make(chan string)
go func() {
defer cxl()
defer close(ch)
for _, s := range []string{"h", "e", "l", "l", "o"} {
select {
case <-ctx.Done():
case ch <- s:
}
}
}()
return ch
}(procCtx)
var items <-chan interface{} = chans.FromStringCh(strs)
for v := range items {
fmt.Println(v)
}
}
Output: h e l l o
func Generator ¶ added in v0.2.5
func Generator[T any](done <-chan struct{}, in ...T) <-chan T
Generator -- 指定されたデータを出力するチャネルを生成します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 1, 2, 3, 4, 5)
for v := range numbers {
fmt.Println(v)
}
}
Output: 1 2 3 4 5
func GeneratorContext ¶ added in v0.5.3
GeneratorContext は、Generator の context.Context 版です.
func Interval ¶ added in v0.2.0
Interval -- 指定した間隔でデータを出力していくチャネルを生成します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
numbers = chans.GeneratorContext(procCtx, 1, 2, 3, 4, 5)
withInterval = chans.IntervalContext(procCtx, numbers, 5*time.Millisecond)
)
begin := time.Now()
for range withInterval {
// no-op
}
elapsed := time.Since(begin)
fmt.Printf("elapsed <= 35msec: %v\n", elapsed < 50*time.Millisecond)
}
Output: elapsed <= 35msec: true
func IntervalContext ¶ added in v0.5.3
IntervalContext は、Interval の context.Context 版です.
func Loop ¶ added in v0.2.0
Loop -- 指定された開始と終了の間、データを返し続けるチャネルを生成します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 10*time.Millisecond)
)
defer mainCxl()
defer procCxl()
for v := range chans.LoopContext(procCtx, 0, 5) {
fmt.Println(v)
}
}
Output: 0 1 2 3 4
func LoopContext ¶ added in v0.5.3
LoopContext は、Loop の context.Context 版です.
func LoopInfinite ¶ added in v0.2.0
func LoopInfinite(done <-chan struct{}) <-chan int
LoopInfinite -- 無限にループして、データを返し続けるチャネルを生成します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
// contexts
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 10*time.Millisecond)
)
defer mainCxl()
defer procCxl()
// channels
var (
infinite = chans.LoopInfiniteContext(procCtx)
takes = chans.TakeContext(procCtx, infinite, 5)
)
for v := range takes {
fmt.Println(v)
}
}
Output: 0 1 2 3 4
func LoopInfiniteContext ¶ added in v0.5.3
LoopInfiniteContext は、 LoopInfinite の context.Context 版です.
func Map ¶ added in v0.2.0
Map -- 関数 fn を入力チャネル in の各要素に適用した結果を返すチャネルを生成します。
戻り値のチャネルから取得できるデータ型は、*chans.MapValue となっています。
for v := range chans.Map(done, inCh, fn) {
// v.Before で元の値、 v.After で適用後の値が取得できる
}
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
numbers = chans.GeneratorContext(procCtx, 1, 2, 3)
fn = func(original int) (after int) {
return original * 2
}
)
for v := range chans.MapContext(procCtx, numbers, fn) {
fmt.Printf("%v,%v\n", v.Before, v.After)
}
}
Output: 1,2 2,4 3,6
func MapContext ¶ added in v0.5.3
func MapContext[T any, R any](ctx context.Context, in <-chan T, fn MapFunc[T, R]) <-chan *MapValue[T, R]
MapContext は、Map の context.Context 版です.
func Merge ¶ added in v0.5.6
func Merge[T any](done <-chan struct{}, channels ...<-chan T) <-chan T
Merge は、複数のチャネルシーケンスを纏めて一つのチャネルから出力するようにします。 取り出される順番は不定です。FanIn関数のエイリアスです。
出力順を守りたい場合は Concat を利用してください。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 100*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
inCh1 = chans.GeneratorContext(procCtx, 1, 2, 3)
inCh2 = chans.GeneratorContext(procCtx, 4, 5, 6)
)
for v := range chans.MergeContext(procCtx, inCh1, inCh2) {
fmt.Println(v)
}
}
Output: 1 2 3 4 5 6
func MergeContext ¶ added in v0.5.6
MergeContext は、 Merge の context.Context 版です。
func OrDone ¶ added in v0.1.5
func OrDone[T any](done <-chan struct{}, in <-chan T) <-chan T
OrDone -- 指定された終了チャネルと入力用チャネルのどちらかが閉じたら閉じるチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 1*time.Minute)
genCtx, genCxl = context.WithCancel(mainCtx)
)
defer mainCxl()
defer procCxl()
defer genCxl()
inCh := chans.GeneratorContext(genCtx, "h", "e", "l", "l", "o")
var result []interface{}
for v := range chans.OrDoneContext(procCtx, inCh) {
func() {
defer procCxl()
result = append(result, v)
}()
}
fmt.Printf("len(result) <= 2: %v", len(result) <= 2)
}
Output: len(result) <= 2: true
func OrDoneContext ¶ added in v0.5.3
OrDoneContext は、OrDone の context.Context 版です.
func RecvAny ¶ added in v0.3.3
RecvAny -- 指定されたチャネルリストから一つ値を取得します。どのチャネルが選択されるかは非決定的です。
See: chans.Select
Example ¶
package main
import (
"fmt"
"github.com/devlights/gomy/chans"
)
func main() {
var (
ch1 = make(chan interface{})
ch2 = make(chan interface{})
)
defer close(ch1)
defer close(ch2)
go func() {
ch1 <- 1
}()
go func() {
ch2 <- 2
}()
_, v1, _ := chans.RecvAny(ch1, ch2)
_, v2, _ := chans.RecvAny(ch1, ch2)
fmt.Println(v1)
fmt.Println(v2)
}
Output: 1 2
func Repeat ¶ added in v0.1.5
func Repeat[T any](done <-chan struct{}, values ...T) <-chan T
Repeat -- 指定した値を永遠と繰り返すチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
repeats := chans.RepeatContext(procCtx, 1, 2, 3)
takes := chans.TakeContext(procCtx, repeats, 6)
for v := range takes {
fmt.Println(v)
}
}
Output: 1 2 3 1 2 3
func RepeatContext ¶ added in v0.5.3
RepeatContext は、Repeat の context.Context 版です.
func RepeatFn ¶ added in v0.1.5
func RepeatFn[T any](done <-chan struct{}, fn func() T) <-chan T
RepeatFn -- 指定した関数を永遠と繰り返し、その戻り値を返すチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
ch := make(chan int)
go func() {
defer close(ch)
for {
for _, v := range []int{1, 2, 3} {
select {
case <-procCtx.Done():
return
case ch <- v:
}
}
}
}()
repeats := chans.RepeatFnContext(procCtx, func() int { return <-ch })
takes := chans.TakeContext(procCtx, repeats, 6)
for v := range takes {
fmt.Println(v)
}
}
Output: 1 2 3 1 2 3
func RepeatFnContext ¶ added in v0.5.3
RepeatFnContext は、RepeatFn の context.Context 版です.
func Select ¶ added in v0.3.3
Select -- 指定されたチャネルリストから一つ値を取得します。どのチャネルが選択されるかは非決定的です。
内部で reflect.Select() を呼び出しており、戻り値はそれに準じています。
REFERENCES:
- https://pkg.go.dev/reflect#Select
- https://pkg.go.dev/reflect#SelectCase
- https://dev.to/hgsgtk/handling-with-arbitrary-channels-by-reflectselect-4d5g
Example ¶
package main
import (
"fmt"
"github.com/devlights/gomy/chans"
)
func main() {
var (
ch1 = make(chan interface{})
ch2 = make(chan interface{})
)
defer close(ch1)
defer close(ch2)
go func() {
ch1 <- 1
}()
go func() {
ch2 <- 2
}()
_, v1, _ := chans.Select(ch1, ch2)
_, v2, _ := chans.Select(ch1, ch2)
fmt.Println(v1)
fmt.Println(v2)
}
Output: 1 2
func Skip ¶ added in v0.2.0
Skip -- 指定した個数分、入力用チャネルから値をスキップするチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 1, 1, 1, 4, 5)
items := chans.SkipContext(procCtx, numbers, 3)
for v := range items {
fmt.Println(v)
}
}
Output: 4 5
func SkipContext ¶ added in v0.5.3
SkipContext は、Skip の context.Context 版です.
func SkipWhile ¶ added in v0.2.0
func SkipWhile[T comparable](done <-chan struct{}, in <-chan T, value T) <-chan T
SkipWhile -- 入力用チャネルから取得した値が指定した値と同一である間、値をスキップし続けるチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 1, 1, 1, 4, 5)
items := chans.SkipWhileContext(procCtx, numbers, 1)
for v := range items {
fmt.Println(v)
}
}
Output: 4 5
func SkipWhileContext ¶ added in v0.5.3
func SkipWhileContext[T comparable](ctx context.Context, in <-chan T, value T) <-chan T
SkipWhileContext は、SkipWhile の context.Context 版です.
func SkipWhileFn ¶ added in v0.2.0
func SkipWhileFn[T comparable](done <-chan struct{}, in <-chan T, fn func() T) <-chan T
SkipWhileFn -- 入力用チャネルから取得した値が指定した関数の戻り値と同一である間、値をスキップし続けるチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 1, 1, 1, 4, 5)
items := chans.SkipWhileFnContext(procCtx, numbers, func() int { return 1 })
for v := range items {
fmt.Println(v)
}
}
Output: 4 5
func SkipWhileFnContext ¶ added in v0.5.3
func SkipWhileFnContext[T comparable](ctx context.Context, in <-chan T, fn func() T) <-chan T
SkipWhileFnContext は、SkipWhileFn の context.Context 版です.
func Slice ¶ added in v0.5.4
func Slice[T any](done <-chan struct{}, in <-chan T) []T
Slice は、指定されたチャネルから情報を読み取りスライスにして返します.
本処理は、done もしくは in のどちらかがクローズされるまで結果を返しません。
func SliceContext ¶ added in v0.5.4
SliceContext は、Slice の context.Context 版です.
Example ¶
package main
import (
"context"
"fmt"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
ctx, cxl = context.WithCancel(rootCtx)
)
defer cxl()
var (
values = []int{1, 2, 3, 4, 5}
in = chans.GeneratorContext(ctx, values...)
out = chans.SliceContext(ctx, in)
)
fmt.Printf("%[1]v (%[1]T)", out)
}
Output: [1 2 3 4 5] ([]int)
func Take ¶ added in v0.1.5
Take -- 指定した個数分、入力用チャネルから値を取得するチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 1, 2, 3, 4, 5)
takes := chans.TakeContext(procCtx, numbers, 3)
for v := range takes {
fmt.Println(v)
}
}
Output: 1 2 3
func TakeContext ¶ added in v0.5.3
TakeContext は、Take の context.Context 版です.
func TakeWhile ¶ added in v0.1.5
func TakeWhile[T comparable](done <-chan struct{}, in <-chan T, value T) <-chan T
TakeWhile -- 入力用チャネルから取得した値が指定した値と同一である間、値を取得し続けるチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 1, 1, 1, 4, 1)
takes := chans.TakeWhileContext(procCtx, numbers, 1)
for v := range takes {
fmt.Println(v)
}
}
Output: 1 1 1
func TakeWhileContext ¶ added in v0.5.3
func TakeWhileContext[T comparable](ctx context.Context, in <-chan T, value T) <-chan T
TakeWhileContext は、TakeWhile の context.Context 版です.
func TakeWhileFn ¶ added in v0.1.5
func TakeWhileFn[T comparable](done <-chan struct{}, in <-chan T, fn func() T) <-chan T
TakeWhileFn -- 入力用チャネルから取得した値が指定した関数の戻り値と同一である間、値を取得し続けるチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 1, 1, 1, 4, 1)
takes := chans.TakeWhileFnContext(procCtx, numbers, func() int { return 1 })
for v := range takes {
fmt.Println(v)
}
}
Output: 1 1 1
func TakeWhileFnContext ¶ added in v0.5.3
func TakeWhileFnContext[T comparable](ctx context.Context, in <-chan T, fn func() T) <-chan T
TakeWhileFnContext は、TakeWhileFn の context.Context 版です.
func Tee ¶ added in v0.1.5
func Tee[T any](done <-chan struct{}, in <-chan T) (<-chan T, <-chan T)
Tee -- Unix の tee コマンドのように一つの入力を2つに複製するチャネルを返します。
Example ¶
package main
import (
"context"
"fmt"
"sync"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
numbers := chans.GeneratorContext(procCtx, 1)
ch1, ch2 := chans.TeeContext(procCtx, numbers)
var wg sync.WaitGroup
for _, ch := range []<-chan int{ch1, ch2} {
wg.Add(1)
go func(ch <-chan int) {
defer wg.Done()
for v := range ch {
fmt.Println(v)
}
}(ch)
}
wg.Wait()
}
Output: 1 1
func TeeContext ¶ added in v0.5.3
TeeContext は、Tee の context.Context 版です.
func ToInt ¶ added in v0.1.5
ToInt -- 入力用チャネルから値を取得し、数値に変換するチャネルを返します。
数値に変換することが出来なかった場合は、引数 failedValue を出力用チャネルに送ります。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
gens <-chan int = chans.GeneratorContext(procCtx, 1, 2)
ints <-chan int = chans.ToInt(procCtx.Done(), gens, -1)
)
for v := range ints {
fmt.Println(v)
}
}
Output: 1 2
func ToString ¶ added in v0.1.5
ToString -- 入力用チャネルから値を取得し、文字列に変換するチャネルを返します。
文字列に変換することが出来なかった場合は、引数 failedValue を出力用チャネルに送ります。
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
var (
rootCtx = context.Background()
mainCtx, mainCxl = context.WithCancel(rootCtx)
procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
)
defer mainCxl()
defer procCxl()
var (
gens <-chan string = chans.GeneratorContext(procCtx, "hello", "world")
strs <-chan string = chans.ToString(procCtx.Done(), gens, "")
)
for v := range strs {
fmt.Println(v)
}
}
Output: hello world
func WhenAll ¶
func WhenAll(channels ...<-chan struct{}) <-chan struct{}
WhenAll -- 指定した1つ以上のチャネルの全てが閉じられたら、閉じるチャネルを返します。
チャネルを一つも渡さずに呼び出すと、既に close 済みのチャネルを返します。
Example ¶
package main
import (
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
fn := func(tlimit time.Duration) <-chan struct{} {
done := make(chan struct{})
go func() {
defer close(done)
time.Sleep(tlimit)
}()
return done
}
done1 := fn(100 * time.Millisecond)
done2 := fn(200 * time.Millisecond)
done3 := fn(300 * time.Millisecond)
start := time.Now()
<-chans.WhenAll(done1, done2, done3)
elapsed := time.Since(start)
fmt.Printf("elapsed: about 300msec ==> %v\n", elapsed >= 299*time.Millisecond)
}
Output: elapsed: about 300msec ==> true
func WhenAllContext ¶ added in v0.5.3
WhenAllContext は、 WhenAll の context.Context 版です.
func WhenAny ¶
func WhenAny(channels ...<-chan struct{}) <-chan struct{}
WhenAny -- 指定した1つ以上のチャネルのどれかが1つが閉じられたら、閉じるチャネルを返します。
チャネルを一つも渡さずに呼び出すと、既に close 済みのチャネルを返します。
Example ¶
package main
import (
"fmt"
"time"
"github.com/devlights/gomy/chans"
)
func main() {
fn := func(tlimit time.Duration) <-chan struct{} {
done := make(chan struct{})
go func() {
defer close(done)
time.Sleep(tlimit)
}()
return done
}
done1 := fn(100 * time.Millisecond)
done2 := fn(200 * time.Millisecond)
done3 := fn(300 * time.Millisecond)
start := time.Now()
<-chans.WhenAny(done1, done2, done3)
elapsed := time.Since(start)
fmt.Printf("elapsed: about 100msec ==> %v\n", elapsed <= 110*time.Millisecond)
}
Output: elapsed: about 100msec ==> true
Types ¶
type SelectValue ¶ added in v0.3.3
SelectValue -- chans.RecvAll() で利用されるデータ型です.
func RecvAll ¶ added in v0.3.3
func RecvAll(chs ...chan any) []SelectValue
RecvAll -- 指定されたチャネルリストの全てから1つ値を取得して返却します。
Example ¶
package main
import (
"fmt"
"github.com/devlights/gomy/chans"
)
func main() {
var (
ch1 = make(chan interface{})
ch2 = make(chan interface{})
)
defer close(ch1)
defer close(ch2)
go func() {
ch1 <- 1
}()
go func() {
ch2 <- 2
}()
for _, v := range chans.RecvAll(ch1, ch2) {
fmt.Printf("chosen:%d,value:%v\n", v.Chosen, v.Value)
}
}
Output: chosen:0,value:1 chosen:1,value:2
func (SelectValue) Eq ¶ added in v0.3.3
func (me SelectValue) Eq(other SelectValue) bool
Eq -- 同じデータかどうかを判定します.