chans

package
v0.4.7 Latest Latest
Warning

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

Go to latest
Published: Jul 21, 2022 License: MIT Imports: 5 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 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 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 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 Concat added in v0.1.7

func Concat[T any](done <-chan struct{}, chList ...<-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 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 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 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 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 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 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 に渡して 真 となったデータを返すチャネルを生成します。

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 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 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 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 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 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 Map added in v0.2.0

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

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 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 RecvAny added in v0.3.3

func RecvAny(chs ...chan interface{}) (chosen int, v interface{}, 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 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 Select added in v0.3.3

func Select(chs ...chan interface{}) (chosen int, v interface{}, 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 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 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 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 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 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 Tee added in v0.1.5

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

Tee -- Unix の tee コマンドのように一つの入力を2つに複製するチャネルを返します。

noinspection GoNilness

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 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[T any](channels ...<-chan T) <-chan T

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 WhenAny

func WhenAny[T any](channels ...<-chan T) <-chan T

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 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] func(T) T

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

type MapValue added in v0.2.0

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

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

type SelectValue added in v0.3.3

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

SelectValue -- chans.RecvAll() で利用されるデータ型です.

func RecvAll added in v0.3.3

func RecvAll(chs ...chan interface{}) []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