chans

package
v0.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2022 License: MIT Imports: 6 Imported by: 11

Documentation

Overview

Package chans は、チャネルに関するユーティリティが配置されています。

Index

Examples

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.Generator(procCtx.Done(), 1, 2, 3)
		chSeq <- chans.Generator(procCtx.Done(), 4, 5, 6)
	}()

	for v := range chans.Bridge(procCtx.Done(), chSeq) {
		fmt.Println(v)
	}

}
Output:

1
2
3
4
5
6

func BridgeContext added in v0.5.3

func BridgeContext[T any](ctx context.Context, chanCh <-chan <-chan T) <-chan T

BridgeContext-- Bridge の context.Context 版です。

func Buffer added in v0.2.18

func Buffer[T any](done <-chan struct{}, in <-chan T, count int) <-chan []T

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.Generator(procCtx.Done(), data...)
	chunks := chans.Buffer(procCtx.Done(), numbers, count)

	for chunk := range chunks {
		fmt.Println(chunk)
	}

}
Output:

[1 2 3]
[4 5 6]
[7]

func BufferContext added in v0.5.3

func BufferContext[T any](ctx context.Context, in <-chan T, count int) <-chan []T

BufferContext は、Bridge の context.Context 版です.

func Chain added in v0.2.14

func Chain(done, base <-chan struct{}, next func(finished time.Time)) <-chan struct{}

Chain -- 指定された base チャネルがクローズした後に next で指定された関数を呼び出します.

done チャネルがクローズした場合、 next は実行されません。

Example
package main

import (
	"fmt"
	"time"

	"github.com/devlights/gomy/chans"
)

func main() {
	// functions
	var (
		makeGoroutine = func() <-chan struct{} {
			ch := make(chan struct{})
			go func() {
				defer close(ch)
				time.Sleep(100 * time.Millisecond)
				fmt.Println("base")
			}()
			return ch
		}
	)

	// channels
	var (
		done = make(chan struct{})
		base = makeGoroutine()
	)

	defer close(done)

	chain1 := chans.Chain(done, base, func(t time.Time) {
		fmt.Println("chain-1")
	})

	chain2 := chans.Chain(done, chain1, func(t time.Time) {
		fmt.Println("chain-2")
	})

	<-chans.WhenAll(base, chain1, chain2)

}
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

func Chunk[T any](done <-chan struct{}, in <-chan T, count int) <-chan []T

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.Generator(procCtx.Done(), 1, 2, 3, 4, 5, 6, 7)
	chunks := chans.Chunk(procCtx.Done(), numbers, 3)

	for chunk := range chunks {
		fmt.Println(chunk)
	}

}
Output:

[1 2 3]
[4 5 6]
[7]

func ChunkContext added in v0.5.3

func ChunkContext[T any](ctx context.Context, in <-chan T, count int) <-chan []T

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.Generator(procCtx.Done(), 1, 2, 3)
	nums2 := chans.Generator(procCtx.Done(), 4, 5, 6)

	for v := range chans.Concat(procCtx.Done(), nums1, nums2) {
		fmt.Println(v)
	}

}
Output:

1
2
3
4
5
6

func ConcatContext added in v0.5.3

func ConcatContext[T any](ctx context.Context, channels ...<-chan T) <-chan T

ConcatContext は、 Concat の context.Context 版です.

func Convert added in v0.4.2

func Convert[F any, T any](done <-chan struct{}, in <-chan F, fn func(F) T) <-chan T

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 (
		done      = procCtx.Done()
		numbers   = chans.Generator(done, 1, 2, 3)
		converted = chans.Convert(done, 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

func ConvertContext[F any, T any](ctx context.Context, in <-chan F, fn func(F) T) <-chan T

ConvertContext は、 Convert の context.Context 版です.

func Enumerate added in v0.2.0

func Enumerate[T any](done <-chan struct{}, in <-chan T) <-chan *IterValue[T]

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.Generator(procCtx.Done(), 9, 8, 7)
	values := chans.Enumerate(procCtx.Done(), 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

func EnumerateContext[T any](ctx context.Context, in <-chan T) <-chan *IterValue[T]

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.Generator(procCtx.Done(), 1, 2, 3)
	numStream2 := chans.Generator(procCtx.Done(), 4, 5, 6)

	for v := range chans.FanIn(procCtx.Done(), numStream1, numStream2) {
		fmt.Println(v)
	}

}
Output:

4
1
5
2
3
6

func FanInContext added in v0.5.3

func FanInContext[T any](ctx context.Context, channels ...<-chan T) <-chan T

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"
)

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.Generator(procCtx.Done(), 1, 2, 3, 4, 5, 6)
		callback = func(v int) { fmt.Println(v) }
	)

	dones := chans.FanOut(procCtx.Done(), nums, 3, callback)
	<-chans.WhenAll(dones...)

}
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

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.Generator(procCtx.Done(), 1, 2, 3, 4, 5, 6)
		callback = func(v int) { fmt.Println(v) }
	)

	wg := chans.FanOutWg(procCtx.Done(), 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

func Filter[T any](done <-chan struct{}, in <-chan T, predicate func(T) bool) <-chan T

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.Generator(procCtx.Done(), 1, 2, 3, 4, 5)
		predicate = func(v int) bool {
			return v%2 == 0
		}
	)

	for v := range chans.Filter(procCtx.Done(), numbers, predicate) {
		fmt.Println(v)
	}

}
Output:

2
4

func FilterContext added in v0.5.3

func FilterContext[T any](ctx context.Context, in <-chan T, predicate func(T) bool) <-chan T

FilterContext は、Filter の context.Context 版です.

func ForEach added in v0.2.0

func ForEach[T any](done <-chan struct{}, in ...T) <-chan 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()

	for v := range chans.ForEach(procCtx.Done(), 1, 2, 3) {
		fmt.Println(v)
	}

}
Output:

1
2
3

func ForEachContext added in v0.5.3

func ForEachContext[T any](ctx context.Context, in ...T) <-chan T

ForEachContext は、ForEach の context.Context 版です.

func FromIntCh added in v0.2.0

func FromIntCh(ch <-chan int) <-chan any

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

func FromStringCh(ch <-chan string) <-chan any

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 -- 指定されたデータを出力するチャネルを生成します。

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()

	numbers := chans.Generator(procCtx.Done(), 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

func GeneratorContext[T any](ctx context.Context, in ...T) <-chan T

GeneratorContext は、Generator の context.Context 版です.

func Interval added in v0.2.0

func Interval[T any](done <-chan struct{}, in <-chan T, interval time.Duration) <-chan T

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.Generator(procCtx.Done(), 1, 2, 3, 4, 5)
		withInterval = chans.Interval(procCtx.Done(), 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

func IntervalContext[T any](ctx context.Context, in <-chan T, interval time.Duration) <-chan T

IntervalContext は、Interval の context.Context 版です.

func Loop added in v0.2.0

func Loop(done <-chan struct{}, start, end int) <-chan int

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.Loop(procCtx.Done(), 0, 5) {
		fmt.Println(v)
	}

}
Output:

0
1
2
3
4

func LoopContext added in v0.5.3

func LoopContext(ctx context.Context, start, end int) <-chan int

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.LoopInfinite(procCtx.Done())
		takes    = chans.Take(procCtx.Done(), chans.FromIntCh(infinite), 5)
	)

	for v := range takes {
		fmt.Println(v)
	}

}
Output:

0
1
2
3
4

func LoopInfiniteContext added in v0.5.3

func LoopInfiniteContext(ctx context.Context) <-chan int

LoopInfiniteContext は、 LoopInfinite の context.Context 版です.

func Map added in v0.2.0

func Map[T any, R any](done <-chan struct{}, in <-chan T, fn MapFunc[T, R]) <-chan *MapValue[T, R]

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.Generator(procCtx.Done(), 1, 2, 3)
		fn      = func(original int) (after int) {
			return original * 2
		}
	)

	for v := range chans.Map(procCtx.Done(), 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 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.Generator(genCtx.Done(), "h", "e", "l", "l", "o")

	var result []interface{}
	for v := range chans.OrDone(procCtx.Done(), 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

func OrDoneContext[T any](ctx context.Context, in <-chan T) <-chan T

OrDoneContext は、OrDone の context.Context 版です.

func RecvAny added in v0.3.3

func RecvAny(chs ...chan any) (chosen int, v any, ok bool)

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.Repeat(procCtx.Done(), 1, 2, 3)
	takes := chans.Take(procCtx.Done(), repeats, 6)

	for v := range takes {
		fmt.Println(v)
	}

}
Output:

1
2
3
1
2
3

func RepeatContext added in v0.5.3

func RepeatContext[T any](ctx context.Context, values ...T) <-chan T

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 interface{})
	go func() {
		defer close(ch)
		for {
			for _, v := range []int{1, 2, 3} {
				select {
				case <-procCtx.Done():
					return
				case ch <- v:
				}
			}
		}
	}()

	repeats := chans.RepeatFn(procCtx.Done(), func() interface{} { return <-ch })
	takes := chans.Take(procCtx.Done(), repeats, 6)

	for v := range takes {
		fmt.Println(v)
	}

}
Output:

1
2
3
1
2
3

func RepeatFnContext added in v0.5.3

func RepeatFnContext[T any](ctx context.Context, fn func() T) <-chan T

RepeatFnContext は、RepeatFn の context.Context 版です.

func Select added in v0.3.3

func Select(chs ...chan any) (chosen int, v any, ok bool)

Select -- 指定されたチャネルリストから一つ値を取得します。どのチャネルが選択されるかは非決定的です。

内部で reflect.Select() を呼び出しており、戻り値はそれに準じています。

REFERENCES:

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

func Skip[T any](done <-chan struct{}, in <-chan T, count int) <-chan T

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.Generator(procCtx.Done(), 1, 1, 1, 4, 5)
	items := chans.Skip(procCtx.Done(), numbers, 3)

	for v := range items {
		fmt.Println(v)
	}

}
Output:

4
5

func SkipContext added in v0.5.3

func SkipContext[T any](ctx context.Context, in <-chan T, count int) <-chan T

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.Generator(procCtx.Done(), 1, 1, 1, 4, 5)
	items := chans.SkipWhile(procCtx.Done(), 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.Generator(procCtx.Done(), 1, 1, 1, 4, 5)
	items := chans.SkipWhileFn(procCtx.Done(), 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 Take added in v0.1.5

func Take[T any](done <-chan struct{}, in <-chan T, count int) <-chan T

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.ForEach(procCtx.Done(), 1, 2, 3, 4, 5)
	takes := chans.Take(procCtx.Done(), numbers, 3)

	for v := range takes {
		fmt.Println(v)
	}

}
Output:

1
2
3

func TakeContext added in v0.5.3

func TakeContext[T any](ctx context.Context, in <-chan T, count int) <-chan T

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.ForEach(procCtx.Done(), 1, 1, 1, 4, 1)
	takes := chans.TakeWhile(procCtx.Done(), 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.ForEach(procCtx.Done(), 1, 1, 1, 4, 1)
	takes := chans.TakeWhileFn(procCtx.Done(), 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.Generator(procCtx.Done(), 1)
	ch1, ch2 := chans.Tee(procCtx.Done(), 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

func TeeContext[T any](ctx context.Context, in <-chan T) (<-chan T, <-chan T)

TeeContext は、Tee の context.Context 版です.

func ToInt added in v0.1.5

func ToInt[T any](done <-chan struct{}, in <-chan T, failedValue int) <-chan int

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.Generator(procCtx.Done(), 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

func ToString[T any](done <-chan struct{}, in <-chan T, failedValue string) <-chan string

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.Generator(procCtx.Done(), "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

func WhenAllContext(pCtx context.Context, channels ...<-chan struct{}) context.Context

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

func WhenAnyContext added in v0.5.3

func WhenAnyContext(pCtx context.Context, channels ...<-chan struct{}) context.Context

WhenAnyContext は、WhenAny の context.Context 版です.

Types

type IterValue added in v0.2.0

type IterValue[T any] struct {
	Index int // インデックス
	Value T   // 値
}

IterValue -- chans.Enumerate() にて利用されるデータ型です。

type MapFunc added in v0.2.0

type MapFunc[T any, R any] func(T) R

MapFunc -- chans.Map にて利用されるチャネルの各要素に適用する関数です。

type MapValue added in v0.2.0

type MapValue[T any, R any] struct {
	Before T // 元の値
	After  R // 適用後の値
}

MapValue -- chans.Map にて利用されるデータ型です。

type SelectValue added in v0.3.3

type SelectValue struct {
	Chosen int // 選択されたチャネルのインデックス
	Value  any // 受信した値
}

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 -- 同じデータかどうかを判定します.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL