1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-17 03:02:28 +08:00

doc: add example and update docment for channel

This commit is contained in:
dudaodong
2022-12-31 13:12:16 +08:00
parent 54834dba4c
commit cc54dd7ec9
5 changed files with 442 additions and 208 deletions

View File

@@ -11,17 +11,18 @@ import (
// Channel is a logic object which can generate or manipulate go channel // Channel is a logic object which can generate or manipulate go channel
// all methods of Channel are in the book tilted《Concurrency in Go》 // all methods of Channel are in the book tilted《Concurrency in Go》
type Channel struct { type Channel[T any] struct {
} }
// NewChannel return a Channel instance // NewChannel return a Channel instance
func NewChannel() *Channel { func NewChannel[T any]() *Channel[T] {
return &Channel{} return &Channel[T]{}
} }
// Generate a data of type any chan, put param `values` into the chan // Generate a data of type any channel, put param values into the channel.
func (c *Channel) Generate(ctx context.Context, values ...any) <-chan any { // Play:
dataStream := make(chan any) func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T {
dataStream := make(chan T)
go func() { go func() {
defer close(dataStream) defer close(dataStream)
@@ -38,9 +39,10 @@ func (c *Channel) Generate(ctx context.Context, values ...any) <-chan any {
return dataStream return dataStream
} }
// Repeat return a data of type any chan, put param `values` into the chan repeatly until cancel the context. // Repeat return a data of type any channel, put param `values` into the channel repeatly until cancel the context.
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any { // Play:
dataStream := make(chan any) func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T {
dataStream := make(chan T)
go func() { go func() {
defer close(dataStream) defer close(dataStream)
@@ -57,10 +59,11 @@ func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any {
return dataStream return dataStream
} }
// RepeatFn return a chan, excutes fn repeatly, and put the result into retruned chan // RepeatFn return a channel, excutes fn repeatly, and put the result into retruned channel
// until close the `done` channel // until close the `done` channel.
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any { // Play:
dataStream := make(chan any) func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T {
dataStream := make(chan T)
go func() { go func() {
defer close(dataStream) defer close(dataStream)
@@ -75,9 +78,10 @@ func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any {
return dataStream return dataStream
} }
// Take return a chan whose values are tahken from another chan // Take return a channel whose values are taken from another channel.
func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int) <-chan any { // Play:
takeStream := make(chan any) func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T {
takeStream := make(chan T)
go func() { go func() {
defer close(takeStream) defer close(takeStream)
@@ -94,16 +98,17 @@ func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int)
return takeStream return takeStream
} }
// FanIn merge multiple channels into one channel // FanIn merge multiple channels into one channel.
func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any { // Play:
out := make(chan any) func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T {
out := make(chan T)
go func() { go func() {
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(len(channels)) wg.Add(len(channels))
for _, c := range channels { for _, c := range channels {
go func(c <-chan any) { go func(c <-chan T) {
defer wg.Done() defer wg.Done()
for v := range c { for v := range c {
select { select {
@@ -121,10 +126,11 @@ func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any
return out return out
} }
// Tee split one chanel into two channels // Tee split one chanel into two channels.
func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan any) { // Play:
out1 := make(chan any) func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T) {
out2 := make(chan any) out1 := make(chan T)
out2 := make(chan T)
go func() { go func() {
defer close(out1) defer close(out1)
@@ -147,15 +153,16 @@ func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan an
return out1, out2 return out1, out2
} }
// Bridge link multiply channels into one channel // Bridge link multiply channels into one channel.
func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-chan any { // Play:
valStream := make(chan any) func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T {
valStream := make(chan T)
go func() { go func() {
defer close(valStream) defer close(valStream)
for { for {
var stream <-chan any var stream <-chan T
select { select {
case maybeStream, ok := <-chanStream: case maybeStream, ok := <-chanStream:
if !ok { if !ok {
@@ -178,8 +185,9 @@ func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-ch
return valStream return valStream
} }
// Or read one or more channels into one channel, will close when any readin channel is closed // Or read one or more channels into one channel, will close when any readin channel is closed.
func (c *Channel) Or(channels ...<-chan any) <-chan any { // Play:
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T {
switch len(channels) { switch len(channels) {
case 0: case 0:
return nil return nil
@@ -187,7 +195,7 @@ func (c *Channel) Or(channels ...<-chan any) <-chan any {
return channels[0] return channels[0]
} }
orDone := make(chan any) orDone := make(chan T)
go func() { go func() {
defer close(orDone) defer close(orDone)
@@ -199,17 +207,12 @@ func (c *Channel) Or(channels ...<-chan any) <-chan any {
case <-channels[1]: case <-channels[1]:
} }
default: default:
m := len(channels) / 2
select { select {
case <-c.Or(channels[:m]...): case <-channels[0]:
case <-c.Or(channels[m:]...): case <-channels[1]:
case <-channels[2]:
case <-c.Or(append(channels[3:], orDone)...):
} }
// select {
// case <-channels[0]:
// case <-channels[1]:
// case <-channels[2]:
// case <-c.Or(append(channels[3:], orDone)...):
// }
} }
}() }()
@@ -217,8 +220,9 @@ func (c *Channel) Or(channels ...<-chan any) <-chan any {
} }
// OrDone read a channel into another channel, will close until cancel context. // OrDone read a channel into another channel, will close until cancel context.
func (c *Channel) OrDone(ctx context.Context, channel <-chan any) <-chan any { // Play:
valStream := make(chan any) func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T {
valStream := make(chan T)
go func() { go func() {
defer close(valStream) defer close(valStream)

View File

@@ -0,0 +1,196 @@
package concurrency
import (
"context"
"fmt"
"time"
)
func ExampleChannel_Generate() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
intStream := c.Generate(ctx, 1, 2, 3)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
// Output:
// 1
// 2
// 3
}
func ExampleChannel_Repeat() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
for v := range intStream {
fmt.Println(v)
}
// Output:
// 1
// 2
// 1
// 2
}
func ExampleChannel_RepeatFn() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func() string {
return "hello"
}
c := NewChannel[string]()
intStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range intStream {
fmt.Println(v)
}
// Output:
// hello
// hello
// hello
}
func ExampleChannel_Take() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
numbers := make(chan int, 5)
numbers <- 1
numbers <- 2
numbers <- 3
numbers <- 4
numbers <- 5
defer close(numbers)
c := NewChannel[int]()
intStream := c.Take(ctx, numbers, 3)
for v := range intStream {
fmt.Println(v)
}
// Output:
// 1
// 2
// 3
}
func ExampleChannel_FanIn() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
channels := make([]<-chan int, 2)
for i := 0; i < 2; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 2)
}
chs := c.FanIn(ctx, channels...)
for v := range chs {
fmt.Println(v) //1 1 0 0 or 0 0 1 1
}
}
func ExampleChannel_Or() {
sig := func(after time.Duration) <-chan any {
c := make(chan any)
go func() {
defer close(c)
time.Sleep(after)
}()
return c
}
start := time.Now()
c := NewChannel[any]()
<-c.Or(
sig(1*time.Second),
sig(2*time.Second),
sig(3*time.Second),
)
if time.Since(start).Seconds() < 2 {
fmt.Println("ok")
}
// Output:
// ok
}
func ExampleChannel_OrDone() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
for v := range c.OrDone(ctx, intStream) {
fmt.Println(v)
}
// Output:
// 1
// 1
// 1
}
func ExampleChannel_Tee() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 2)
ch1, ch2 := c.Tee(ctx, intStream)
for v := range ch1 {
fmt.Println(v)
fmt.Println(<-ch2)
}
// Output:
// 1
// 1
// 1
// 1
}
func ExampleChannel_Bridge() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
genVals := func() <-chan <-chan int {
out := make(chan (<-chan int))
go func() {
defer close(out)
for i := 1; i <= 5; i++ {
stream := make(chan int, 1)
stream <- i
close(stream)
out <- stream
}
}()
return out
}
for v := range c.Bridge(ctx, genVals()) {
fmt.Println(v)
}
// Output:
// 1
// 2
// 3
// 4
// 5
}

View File

@@ -14,12 +14,9 @@ func TestGenerate(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := NewChannel() c := NewChannel[int]()
intStream := c.Generate(ctx, 1, 2, 3) intStream := c.Generate(ctx, 1, 2, 3)
// for v := range intStream {
// t.Log(v) //1, 2, 3
// }
assert.Equal(1, <-intStream) assert.Equal(1, <-intStream)
assert.Equal(2, <-intStream) assert.Equal(2, <-intStream)
assert.Equal(3, <-intStream) assert.Equal(3, <-intStream)
@@ -31,12 +28,9 @@ func TestRepeat(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := NewChannel() c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5) intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
// for v := range intStream {
// t.Log(v) //1, 2, 1, 2, 1
// }
assert.Equal(1, <-intStream) assert.Equal(1, <-intStream)
assert.Equal(2, <-intStream) assert.Equal(2, <-intStream)
assert.Equal(1, <-intStream) assert.Equal(1, <-intStream)
@@ -50,17 +44,13 @@ func TestRepeatFn(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
fn := func() any { fn := func() string {
s := "a" s := "a"
return s return s
} }
c := NewChannel() c := NewChannel[string]()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3) dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
// for v := range dataStream {
// t.Log(v) //a, a, a
// }
assert.Equal("a", <-dataStream) assert.Equal("a", <-dataStream)
assert.Equal("a", <-dataStream) assert.Equal("a", <-dataStream)
assert.Equal("a", <-dataStream) assert.Equal("a", <-dataStream)
@@ -72,7 +62,7 @@ func TestTake(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
numbers := make(chan any, 5) numbers := make(chan int, 5)
numbers <- 1 numbers <- 1
numbers <- 2 numbers <- 2
numbers <- 3 numbers <- 3
@@ -80,7 +70,7 @@ func TestTake(t *testing.T) {
numbers <- 5 numbers <- 5
defer close(numbers) defer close(numbers)
c := NewChannel() c := NewChannel[int]()
intStream := c.Take(ctx, numbers, 3) intStream := c.Take(ctx, numbers, 3)
assert.Equal(1, <-intStream) assert.Equal(1, <-intStream)
@@ -94,8 +84,8 @@ func TestFanIn(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := NewChannel() c := NewChannel[int]()
channels := make([]<-chan any, 3) channels := make([]<-chan int, 3)
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3) channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3)
@@ -124,7 +114,7 @@ func TestOr(t *testing.T) {
start := time.Now() start := time.Now()
c := NewChannel() c := NewChannel[any]()
<-c.Or( <-c.Or(
sig(1*time.Second), sig(1*time.Second),
sig(2*time.Second), sig(2*time.Second),
@@ -133,9 +123,7 @@ func TestOr(t *testing.T) {
sig(5*time.Second), sig(5*time.Second),
) )
t.Logf("done after %v", time.Since(start)) assert.Equal(true, time.Since(start).Seconds() < 2)
assert.Equal(1, 1)
} }
func TestOrDone(t *testing.T) { func TestOrDone(t *testing.T) {
@@ -144,16 +132,12 @@ func TestOrDone(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := NewChannel() c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3) intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
var res any
for val := range c.OrDone(ctx, intStream) { for val := range c.OrDone(ctx, intStream) {
t.Logf("%v", val) assert.Equal(1, val)
res = val
} }
assert.Equal(1, res)
} }
func TestTee(t *testing.T) { func TestTee(t *testing.T) {
@@ -162,15 +146,13 @@ func TestTee(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := NewChannel() c := NewChannel[int]()
inStream := c.Take(ctx, c.Repeat(ctx, 1), 4) inStream := c.Take(ctx, c.Repeat(ctx, 1), 4)
out1, out2 := c.Tee(ctx, inStream) out1, out2 := c.Tee(ctx, inStream)
for val := range out1 { for val := range out1 {
val1 := val val1 := val
val2 := <-out2 val2 := <-out2
// t.Log("val1 is", val1)
// t.Log("val2 is", val2)
assert.Equal(1, val1) assert.Equal(1, val1)
assert.Equal(1, val2) assert.Equal(1, val2)
} }
@@ -182,13 +164,13 @@ func TestBridge(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := NewChannel() c := NewChannel[int]()
genVals := func() <-chan <-chan any { genVals := func() <-chan <-chan int {
chanStream := make(chan (<-chan any)) chanStream := make(chan (<-chan int))
go func() { go func() {
defer close(chanStream) defer close(chanStream)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
stream := make(chan any, 1) stream := make(chan int, 1)
stream <- i stream <- i
close(stream) close(stream)
chanStream <- stream chanStream <- stream

View File

@@ -38,13 +38,13 @@ import (
## Channel ## Channel
### <span id="NewChannel">NewChannel</span> ### <span id="NewChannel">NewChannel</span>
<p>return a Channel pointer instance.</p> <p>Create a Channel pointer instance.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
type Channel struct {} type Channel[T any] struct
func NewChannel() *Channel func NewChannel[T any]() *Channel[T]
``` ```
<b>Example:</b> <b>Example:</b>
@@ -57,7 +57,7 @@ import (
) )
func main() { func main() {
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
} }
``` ```
@@ -70,7 +70,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-chan any func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
@@ -87,25 +87,30 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
genVals := func() <-chan <-chan any { genVals := func() <-chan <-chan int {
chanStream := make(chan (<-chan any)) out := make(chan (<-chan int))
go func() { go func() {
defer close(chanStream) defer close(out)
for i := 0; i < 10; i++ { for i := 1; i <= 5; i++ {
stream := make(chan any, 1) stream := make(chan int, 1)
stream <- i stream <- i
close(stream) close(stream)
chanStream <- stream out <- stream
} }
}() }()
return chanStream return out
} }
index := 0 for v := range c.Bridge(ctx, genVals()) {
for val := range c.Bridge(ctx, genVals()) { fmt.Println(v)
fmt.Printf("%v ", val) //0 1 2 3 4 5 6 7 8 9
} }
// Output:
// 1
// 2
// 3
// 4
// 5
} }
``` ```
@@ -114,12 +119,12 @@ func main() {
### <span id="FanIn">FanIn</span> ### <span id="FanIn">FanIn</span>
<p>merge multiple channels into one channel until cancel the context.</p> <p>Merge multiple channels into one channel until cancel the context.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
@@ -136,17 +141,17 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
channels := make([]<-chan any, 3) channels := make([]<-chan int, 2)
for i := 0; i < 3; i++ { for i := 0; i < 2; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3) channels[i] = c.Take(ctx, c.Repeat(ctx, i), 2)
} }
mergedChannel := c.FanIn(ctx, channels...) chs := c.FanIn(ctx, channels...)
for val := range mergedChannel { for v := range chs {
fmt.Println("\t%d\n", val) //1,2,1,0,0,1,0,2,2 (order not for sure) fmt.Println(v) //1 1 0 0 or 0 0 1 1
} }
} }
``` ```
@@ -154,12 +159,12 @@ func main() {
### <span id="Repeat">Repeat</span> ### <span id="Repeat">Repeat</span>
<p>Return a chan, put param `values` into the chan repeatly until cancel the context.</p> <p>Return a channel, put param `values` into the channel repeatly until cancel the context.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
@@ -176,12 +181,17 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5) intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
for v := range intStream { for v := range intStream {
fmt.Println(v) //1, 2, 1, 2, 1 fmt.Println(v)
} }
// Output:
// 1
// 2
// 1
// 2
} }
``` ```
@@ -190,12 +200,12 @@ func main() {
### <span id="RepeatFn">RepeatFn</span> ### <span id="RepeatFn">RepeatFn</span>
<p>Return a chan, excutes fn repeatly, and put the result into retruned chan until cancel context.</p> <p>Return a channel, excutes fn repeatly, and put the result into retruned channel until cancel context.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
@@ -212,16 +222,20 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
fn := func() any { fn := func() string {
s := "a" return "hello"
return s
} }
c := concurrency.NewChannel()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range dataStream { c := concurrency.NewChannel[string]()
fmt.Println(v) //a, a, a intStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range intStream {
fmt.Println(v)
} }
// Output:
// hello
// hello
// hello
} }
``` ```
@@ -234,7 +248,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func (c *Channel) Or(channels ...<-chan any) <-chan any func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
@@ -249,7 +263,7 @@ import (
func main() { func main() {
sig := func(after time.Duration) <-chan any { sig := func(after time.Duration) <-chan any {
c := make(chan interface{}) c := make(chan any)
go func() { go func() {
defer close(c) defer close(c)
time.Sleep(after) time.Sleep(after)
@@ -259,13 +273,11 @@ func main() {
start := time.Now() start := time.Now()
c := concurrency.NewChannel() c := concurrency.NewChannel[any]()
<-c.Or( <-c.Or(
sig(1*time.Second), sig(1*time.Second),
sig(2*time.Second), sig(2*time.Second),
sig(3*time.Second), sig(3*time.Second),
sig(4*time.Second),
sig(5*time.Second),
) )
fmt.Println("done after %v", time.Since(start)) //1.003s fmt.Println("done after %v", time.Since(start)) //1.003s
@@ -282,7 +294,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func (c *Channel) OrDone(ctx context.Context, channel <-chan any) <-chan any func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
@@ -299,12 +311,16 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3) intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
for val := range c.OrDone(ctx, intStream) { for v := range c.OrDone(ctx, intStream) {
fmt.Println(val) //1 fmt.Println(v)
} }
// Output:
// 1
// 1
// 1
} }
``` ```
@@ -313,12 +329,12 @@ func main() {
### <span id="Take">Take</span> ### <span id="Take">Take</span>
<p>Return a chan whose values are tahken from another chan until cancel context.</p> <p>Return a channel whose values are tahken from another channel until cancel context.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int) <-chan any func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
@@ -335,7 +351,7 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
numbers := make(chan any, 5) numbers := make(chan int, 5)
numbers <- 1 numbers <- 1
numbers <- 2 numbers <- 2
numbers <- 3 numbers <- 3
@@ -343,12 +359,16 @@ func main() {
numbers <- 5 numbers <- 5
defer close(numbers) defer close(numbers)
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, numbers, 3) intStream := c.Take(ctx, numbers, 3)
for val := range intStream { for v := range intStream {
fmt.Println(val) //1, 2, 3 fmt.Println(v)
} }
// Output:
// 1
// 2
// 3
} }
``` ```
@@ -356,12 +376,12 @@ func main() {
### <span id="Tee">Tee</span> ### <span id="Tee">Tee</span>
<p>Split one chanel into two channels until cancel context.</p> <p>Split one channel into two channels until cancel context.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan any) func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -378,13 +398,19 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
inStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4) intStream := c.Take(ctx, c.Repeat(ctx, 1), 2)
out1, out2 := c.Tee(ctx, inStream) ch1, ch2 := c.Tee(ctx, intStream)
for val := range out1 {
fmt.Println(val) //1 for v := range ch1 {
fmt.Println(<-out2) //1 fmt.Println(v)
fmt.Println(<-ch2)
} }
// Output:
// 1
// 1
// 1
// 1
} }
``` ```

View File

@@ -38,13 +38,13 @@ import (
### Channel ### Channel
### <span id="NewChannel">NewChannel</span> ### <span id="NewChannel">NewChannel</span>
<p>返回一个 Channel 指针实例</p> <p>返回一个Channel指针实例</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
type Channel struct {} type Channel[T any] struct
func NewChannel() *Channel func NewChannel[T any]() *Channel[T]
``` ```
<b>例子:</b> <b>例子:</b>
@@ -57,7 +57,7 @@ import (
) )
func main() { func main() {
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
} }
``` ```
@@ -65,12 +65,12 @@ func main() {
### <span id="Bridge">Bridge</span> ### <span id="Bridge">Bridge</span>
<p>将多个通道链接到一个通道,直到取消上下文。</p> <p>将多个channel链接到一个channel,直到取消上下文。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-chan any func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
``` ```
<b>例子:</b> <b>例子:</b>
@@ -84,28 +84,33 @@ import (
) )
func main() { func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
genVals := func() <-chan <-chan any { genVals := func() <-chan <-chan int {
chanStream := make(chan (<-chan any)) out := make(chan (<-chan int))
go func() { go func() {
defer close(chanStream) defer close(out)
for i := 0; i < 10; i++ { for i := 1; i <= 5; i++ {
stream := make(chan any, 1) stream := make(chan int, 1)
stream <- i stream <- i
close(stream) close(stream)
chanStream <- stream out <- stream
} }
}() }()
return chanStream return out
} }
index := 0 for v := range c.Bridge(ctx, genVals()) {
for val := range c.Bridge(ctx, genVals()) { fmt.Println(v)
fmt.Printf("%v ", val) //0 1 2 3 4 5 6 7 8 9
} }
// Output:
// 1
// 2
// 3
// 4
// 5
} }
``` ```
@@ -114,12 +119,12 @@ func main() {
### <span id="FanIn">FanIn</span> ### <span id="FanIn">FanIn</span>
<p>将多个通道合并为一个通道,直到取消上下文</p> <p>将多个channel合并为一个channel,直到取消上下文</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
``` ```
<b>例子:</b> <b>例子:</b>
@@ -133,20 +138,20 @@ import (
) )
func main() { func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
channels := make([]<-chan any, 3) channels := make([]<-chan int, 2)
for i := 0; i < 3; i++ { for i := 0; i < 2; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3) channels[i] = c.Take(ctx, c.Repeat(ctx, i), 2)
} }
mergedChannel := c.FanIn(ctx, channels...) chs := c.FanIn(ctx, channels...)
for val := range mergedChannel { for v := range chs {
fmt.Println("\t%d\n", val) //1,2,1,0,0,1,0,2,2 (order not for sure) fmt.Println(v) //1 1 0 0 or 0 0 1 1
} }
} }
``` ```
@@ -154,12 +159,12 @@ func main() {
### <span id="Repeat">Repeat</span> ### <span id="Repeat">Repeat</span>
<p>返回一个chan将参数`values`重复放入chan直到取消上下文。</p> <p>返回一个channel,将参数`values`重复放入channel,直到取消上下文。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
``` ```
<b>例子:</b> <b>例子:</b>
@@ -173,15 +178,20 @@ import (
) )
func main() { func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5) intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
for v := range intStream { for v := range intStream {
fmt.Println(v) //1, 2, 1, 2, 1 fmt.Println(v)
} }
// Output:
// 1
// 2
// 1
// 2
} }
``` ```
@@ -190,12 +200,12 @@ func main() {
### <span id="RepeatFn">RepeatFn</span> ### <span id="RepeatFn">RepeatFn</span>
<p>返回一个chan重复执行函数fn并将结果放入返回的chan直到取消上下文。</p> <p>返回一个channel重复执行函数fn并将结果放入返回的chan直到取消上下文。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
``` ```
<b>例子:</b> <b>例子:</b>
@@ -209,19 +219,23 @@ import (
) )
func main() { func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
fn := func() any { fn := func() string {
s := "a" return "hello"
return s
} }
c := concurrency.NewChannel()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range dataStream { c := concurrency.NewChannel[string]()
fmt.Println(v) //a, a, a intStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range intStream {
fmt.Println(v)
} }
// Output:
// hello
// hello
// hello
} }
``` ```
@@ -229,12 +243,12 @@ func main() {
### <span id="Or">Or</span> ### <span id="Or">Or</span>
<p>将一个或多个通道读取到一个通道中,当任何读取通道关闭时将结束读取。</p> <p>将一个或多个channel读取到一个channel中当任何读取channel关闭时将结束读取。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (c *Channel) Or(channels ...<-chan any) <-chan any func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
``` ```
<b>例子:</b> <b>例子:</b>
@@ -249,7 +263,7 @@ import (
func main() { func main() {
sig := func(after time.Duration) <-chan any { sig := func(after time.Duration) <-chan any {
c := make(chan interface{}) c := make(chan any)
go func() { go func() {
defer close(c) defer close(c)
time.Sleep(after) time.Sleep(after)
@@ -259,13 +273,11 @@ func main() {
start := time.Now() start := time.Now()
c := concurrency.NewChannel() c := concurrency.NewChannel[any]()
<-c.Or( <-c.Or(
sig(1*time.Second), sig(1*time.Second),
sig(2*time.Second), sig(2*time.Second),
sig(3*time.Second), sig(3*time.Second),
sig(4*time.Second),
sig(5*time.Second),
) )
fmt.Println("done after %v", time.Since(start)) //1.003s fmt.Println("done after %v", time.Since(start)) //1.003s
@@ -277,12 +289,12 @@ func main() {
### <span id="OrDone">OrDone</span> ### <span id="OrDone">OrDone</span>
<p>将一个通道读入另一个通道,直到取消上下文。</p> <p>将一个channel读入另一个channel,直到取消上下文。.</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (c *Channel) OrDone(ctx context.Context, channel <-chan any) <-chan any func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
``` ```
<b>例子:</b> <b>例子:</b>
@@ -299,12 +311,16 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3) intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
for val := range c.OrDone(ctx, intStream) { for v := range c.OrDone(ctx, intStream) {
fmt.Println(val) //1 fmt.Println(v)
} }
// Output:
// 1
// 1
// 1
} }
``` ```
@@ -313,12 +329,12 @@ func main() {
### <span id="Take">Take</span> ### <span id="Take">Take</span>
<p>返回一个chan其值从另一个chan获取直到取消上下文。</p> <p>返回一个channel其值从另一个channel获取,直到取消上下文。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int) <-chan any func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
``` ```
<b>例子:</b> <b>例子:</b>
@@ -335,7 +351,7 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
numbers := make(chan any, 5) numbers := make(chan int, 5)
numbers <- 1 numbers <- 1
numbers <- 2 numbers <- 2
numbers <- 3 numbers <- 3
@@ -343,12 +359,16 @@ func main() {
numbers <- 5 numbers <- 5
defer close(numbers) defer close(numbers)
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, numbers, 3) intStream := c.Take(ctx, numbers, 3)
for val := range intStream { for v := range intStream {
fmt.Println(val) //1, 2, 3 fmt.Println(v)
} }
// Output:
// 1
// 2
// 3
} }
``` ```
@@ -356,12 +376,12 @@ func main() {
### <span id="Tee">Tee</span> ### <span id="Tee">Tee</span>
<p>将一个通道分成两个通道,直到取消上下文。</p> <p>将一个channel分成两个channel,直到取消上下文。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan any) func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
``` ```
<b>例子:</b> <b>例子:</b>
@@ -378,13 +398,19 @@ func main() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
c := concurrency.NewChannel() c := concurrency.NewChannel[int]()
inStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4) intStream := c.Take(ctx, c.Repeat(ctx, 1), 2)
out1, out2 := c.Tee(ctx, inStream) ch1, ch2 := c.Tee(ctx, intStream)
for val := range out1 {
fmt.Println(val) //1 for v := range ch1 {
fmt.Println(<-out2) //1 fmt.Println(v)
fmt.Println(<-ch2)
} }
// Output:
// 1
// 1
// 1
// 1
} }
``` ```