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

Merge branch 'rc' into v2

This commit is contained in:
dudaodong
2025-02-14 17:13:11 +08:00
6 changed files with 55 additions and 20 deletions

View File

@@ -157,10 +157,10 @@ func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
// Play: https://go.dev/play/p/qmWSy1NVF-Y // Play: https://go.dev/play/p/qmWSy1NVF-Y
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T { func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T {
valStream := make(chan T) valStream := make(chan T)
go func() { go func() {
defer close(valStream) defer close(valStream)
wg := sync.WaitGroup{}
defer wg.Wait()
for { for {
var stream <-chan T var stream <-chan T
select { select {
@@ -169,19 +169,22 @@ func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-c
return return
} }
stream = maybeStream stream = maybeStream
wg.Add(1)
case <-ctx.Done(): case <-ctx.Done():
return return
} }
for val := range c.OrDone(ctx, stream) { go func() {
select { defer wg.Done()
case valStream <- val: for val := range c.OrDone(ctx, stream) {
case <-ctx.Done(): select {
case valStream <- val:
case <-ctx.Done():
}
} }
} }()
} }
}() }()
return valStream return valStream
} }

View File

@@ -168,7 +168,8 @@ func ExampleChannel_Tee() {
func ExampleChannel_Bridge() { func ExampleChannel_Bridge() {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
m1 := make(map[int]int)
m2 := make(map[int]int)
c := NewChannel[int]() c := NewChannel[int]()
genVals := func() <-chan <-chan int { genVals := func() <-chan <-chan int {
out := make(chan (<-chan int)) out := make(chan (<-chan int))
@@ -177,6 +178,7 @@ func ExampleChannel_Bridge() {
for i := 1; i <= 5; i++ { for i := 1; i <= 5; i++ {
stream := make(chan int, 1) stream := make(chan int, 1)
stream <- i stream <- i
m1[i]++
close(stream) close(stream)
out <- stream out <- stream
} }
@@ -185,12 +187,15 @@ func ExampleChannel_Bridge() {
} }
for v := range c.Bridge(ctx, genVals()) { for v := range c.Bridge(ctx, genVals()) {
fmt.Println(v) m2[v]++
}
for k, v := range m1 {
fmt.Println(m2[k] == v)
} }
// Output: // Output:
// 1 // true
// 2 // true
// 3 // true
// 4 // true
// 5 // true
} }

View File

@@ -169,7 +169,8 @@ func TestTee(t *testing.T) {
func TestBridge(t *testing.T) { func TestBridge(t *testing.T) {
t.Parallel() t.Parallel()
assert := internal.NewAssert(t, "TestBridge") assert := internal.NewAssert(t, "TestBridge")
m1 := make(map[int]int)
m2 := make(map[int]int)
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
@@ -181,6 +182,7 @@ func TestBridge(t *testing.T) {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
stream := make(chan int, 1) stream := make(chan int, 1)
stream <- i stream <- i
m1[i]++
close(stream) close(stream)
chanStream <- stream chanStream <- stream
} }
@@ -188,9 +190,11 @@ func TestBridge(t *testing.T) {
return chanStream return chanStream
} }
index := 0
for val := range c.Bridge(ctx, genVals()) { for val := range c.Bridge(ctx, genVals()) {
assert.Equal(index, val) m2[val]++
index++ }
for k, v := range m1 {
assert.Equal(m2[k], v)
} }
} }

View File

@@ -108,6 +108,13 @@ func ToString(value any) string {
if value == nil { if value == nil {
return "" return ""
} }
rv := reflect.ValueOf(value)
if rv.Kind() == reflect.Ptr {
if rv.IsNil() {
return ""
}
return ToString(rv.Elem().Interface())
}
switch val := value.(type) { switch val := value.(type) {
case float32: case float32:

View File

@@ -142,13 +142,24 @@ func TestToString(t *testing.T) {
} }
aStruct := TestStruct{Name: "TestStruct"} aStruct := TestStruct{Name: "TestStruct"}
i32Val := int32(123)
i64Val := int64(123)
iZeroVal := 0
fVal := 12.3
sVal := "abc"
var iNilPointer *int
var sNilPointer *string
cases := []any{ cases := []any{
"", nil, "", nil,
int(0), int8(1), int16(-1), int32(123), int64(123), int(0), int8(1), int16(-1), int32(123), int64(123),
uint(123), uint8(123), uint16(123), uint32(123), uint64(123), uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
float64(12.3), float32(12.3), float64(12.3), float32(12.3),
true, false, true, false,
[]int{1, 2, 3}, aMap, aStruct, []byte{104, 101, 108, 108, 111}} []int{1, 2, 3}, aMap, aStruct, []byte{104, 101, 108, 108, 111},
&i32Val, &i64Val, &fVal, &sVal, &aStruct, iNilPointer, sNilPointer,
&iZeroVal,
}
expected := []string{ expected := []string{
"", "", "", "",
@@ -157,6 +168,8 @@ func TestToString(t *testing.T) {
"12.3", "12.3", "12.3", "12.3",
"true", "false", "true", "false",
"[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello", "[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello",
"123", "123", "12.3", "abc", "{\"Name\":\"TestStruct\"}", "", "",
"0",
} }
for i := 0; i < len(cases); i++ { for i := 0; i < len(cases); i++ {

View File

@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"math" "math"
"reflect" "reflect"
"sort"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@@ -1817,6 +1818,8 @@ func TestFilterConcurrent(t *testing.T) {
nums := []int{1, 2, 3, 4, 5, 6} nums := []int{1, 2, 3, 4, 5, 6}
expected := []int{4, 5, 6} expected := []int{4, 5, 6}
actual := FilterConcurrent(nums, func(_, n int) bool { return n > 3 }, 4) actual := FilterConcurrent(nums, func(_, n int) bool { return n > 3 }, 4)
sort.Ints(actual)
sort.Ints(expected)
assert.Equal(expected, actual) assert.Equal(expected, actual)
}) })
} }