chans

package
v0.3.3 Latest Latest
Warning

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

Go to latest
Published: Mar 29, 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(done <-chan struct{}, chanCh <-chan <-chan interface{}) <-chan interface{}

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 interface{}))
	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(done <-chan struct{}, in <-chan interface{}, count int) <-chan []interface{}

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(finishedTime 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(done <-chan struct{}, in <-chan interface{}, count int) <-chan []interface{}

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(done <-chan struct{}, chList ...<-chan interface{}) <-chan interface{}

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

func Enumerate(done <-chan struct{}, in <-chan interface{}) <-chan interface{}

Enumerate -- 指定された入力チャネルの要素に対してインデックスを付与したデータを返すチャネルを生成します。

戻り値のチャネルから取得できるデータ型は、*chans.IterValue となっています。

for e := range chans.Enumerate(done, inCh) {
	if v, ok := e.(*IterValue); ok {
		// 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 e := range values {
		if v, ok := e.(*chans.IterValue); ok {
			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(done <-chan struct{}, channels ...<-chan interface{}) <-chan interface{}

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(done <-chan struct{}, in <-chan interface{}, workerCount int, callback func(interface{})) []<-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 interface{}) { 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(done <-chan struct{}, in <-chan interface{}, workerCount int, callback func(interface{})) *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 interface{}) { 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(done <-chan struct{}, in <-chan interface{}, predicate func(interface{}) bool) <-chan interface{}

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 interface{}) bool {
			if i, ok := v.(int); ok {
				return i%2 == 0
			}
			return false
		}
	)

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

}
Output:

2
4

func ForEach added in v0.2.0

func ForEach(done <-chan struct{}, in ...interface{}) <-chan interface{}

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 interface{}

FromIntCh -- chan int を chan interface{} に変換します。

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 interface{}

FromStringCh -- chan string を chan interface{} に変換します。

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(done <-chan struct{}, in ...interface{}) <-chan interface{}

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(done <-chan struct{}, in <-chan interface{}, interval time.Duration) <-chan interface{}

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(done <-chan struct{}, in <-chan interface{}, fn MapFunc) <-chan interface{}

Map -- 関数 fn を入力チャネル in の各要素に適用した結果を返すチャネルを生成します。

戻り値のチャネルから取得できるデータ型は、*chans.MapValue となっています。

for m := range chans.Map(done, inCh, fn) {
	if v, ok := m.(*chans.MapValue); ok {
		// 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 interface{}) (after interface{}) {
			if i, ok := original.(int); ok {
				return i * 2
			}
			return nil
		}
	)

	for v := range chans.Map(procCtx.Done(), numbers, fn) {
		if m, ok := v.(*chans.MapValue); ok {
			fmt.Printf("%v,%v\n", m.Before, m.After)
		}
	}

}
Output:

1,2
2,4
3,6

func OrDone added in v0.1.5

func OrDone(done <-chan struct{}, in <-chan interface{}) <-chan interface{}

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(done <-chan struct{}, values ...interface{}) <-chan interface{}

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(done <-chan struct{}, fn func() interface{}) <-chan interface{}

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(done <-chan struct{}, in <-chan interface{}, count int) <-chan interface{}

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(done <-chan struct{}, in <-chan interface{}, value interface{}) <-chan interface{}

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(done <-chan struct{}, in <-chan interface{}, fn func() interface{}) <-chan interface{}

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() interface{} { return 1 })

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

}
Output:

4
5

func Take added in v0.1.5

func Take(done <-chan struct{}, in <-chan interface{}, count int) <-chan interface{}

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(done <-chan struct{}, in <-chan interface{}, value interface{}) <-chan interface{}

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(done <-chan struct{}, in <-chan interface{}, fn func() interface{}) <-chan interface{}

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() interface{} { return 1 })

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

}
Output:

1
1
1

func Tee added in v0.1.5

func Tee(done <-chan struct{}, in <-chan interface{}) (<-chan interface{}, <-chan interface{})

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 interface{}{ch1, ch2} {
		wg.Add(1)
		go func(ch <-chan interface{}) {
			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(done <-chan struct{}, in <-chan interface{}, 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 interface{} = 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(done <-chan struct{}, in <-chan interface{}, 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 interface{} = 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 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 IterValue added in v0.2.0

type IterValue struct {
	Index int         // インデックス
	Value interface{} // 値
}

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

type MapFunc added in v0.2.0

type MapFunc func(interface{}) interface{}

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

type MapValue added in v0.2.0

type MapValue struct {
	Before interface{} // 元の値
	After  interface{} // 適用後の値
}

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