Skip to content

Commit dd338da

Browse files
committed
add reflect-operate-channel
1 parent 6c77fe0 commit dd338da

File tree

7 files changed

+296
-0
lines changed

7 files changed

+296
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package main
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
)
7+
8+
func createCases(rchs []chan int) []reflect.SelectCase {
9+
var cases []reflect.SelectCase
10+
11+
// 创建recv case
12+
for _, ch := range rchs {
13+
cases = append(cases, reflect.SelectCase{
14+
Dir: reflect.SelectRecv,
15+
Chan: reflect.ValueOf(ch),
16+
})
17+
}
18+
return cases
19+
}
20+
21+
func BenchmarkSelect(b *testing.B) {
22+
var c1 = make(chan int)
23+
var c2 = make(chan int)
24+
var c3 = make(chan int)
25+
26+
go func() {
27+
for {
28+
c1 <- 1
29+
}
30+
}()
31+
go func() {
32+
for {
33+
c2 <- 2
34+
}
35+
}()
36+
go func() {
37+
for {
38+
c3 <- 3
39+
}
40+
}()
41+
42+
b.ReportAllocs()
43+
b.ResetTimer()
44+
45+
for i := 0; i < b.N; i++ {
46+
select {
47+
case <-c1:
48+
case <-c2:
49+
case <-c3:
50+
}
51+
}
52+
}
53+
54+
func BenchmarkReflectSelect(b *testing.B) {
55+
var c1 = make(chan int)
56+
var c2 = make(chan int)
57+
var c3 = make(chan int)
58+
59+
go func() {
60+
for {
61+
c1 <- 1
62+
}
63+
}()
64+
go func() {
65+
for {
66+
c2 <- 2
67+
}
68+
}()
69+
go func() {
70+
for {
71+
c3 <- 3
72+
}
73+
}()
74+
75+
chs := createCases([]chan int{c1, c2, c3})
76+
77+
b.ReportAllocs()
78+
b.ResetTimer()
79+
80+
for i := 0; i < b.N; i++ {
81+
_, _, _ = reflect.Select(chs)
82+
}
83+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module demo
2+
3+
go 1.19
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"math/rand"
6+
"reflect"
7+
"sync"
8+
"time"
9+
)
10+
11+
func main() {
12+
var wg sync.WaitGroup
13+
wg.Add(2)
14+
var rchs []chan int
15+
for i := 0; i < 10; i++ {
16+
rchs = append(rchs, make(chan int))
17+
}
18+
19+
// 创建SelectCase
20+
var cases = createRecvCases(rchs, true)
21+
22+
// 消费者goroutine
23+
go func() {
24+
defer wg.Done()
25+
for {
26+
chosen, recv, ok := reflect.Select(cases)
27+
if cases[chosen].Dir == reflect.SelectDefault {
28+
fmt.Println("choose the default")
29+
continue
30+
}
31+
if ok {
32+
fmt.Printf("recv from channel [%d], val=%v\n", chosen, recv)
33+
continue
34+
}
35+
// one of the channels is closed, exit the goroutine
36+
fmt.Printf("channel [%d] closed, select goroutine exit\n", chosen)
37+
return
38+
}
39+
}()
40+
41+
// 生产者goroutine
42+
go func() {
43+
defer wg.Done()
44+
var n int
45+
s := rand.NewSource(time.Now().Unix())
46+
r := rand.New(s)
47+
for i := 0; i < 10; i++ {
48+
n = r.Intn(10)
49+
rchs[n] <- n
50+
}
51+
close(rchs[n])
52+
}()
53+
54+
wg.Wait()
55+
}
56+
57+
func createRecvCases(rchs []chan int, withDefault bool) []reflect.SelectCase {
58+
var cases []reflect.SelectCase
59+
60+
// 创建recv case
61+
for _, ch := range rchs {
62+
cases = append(cases, reflect.SelectCase{
63+
Dir: reflect.SelectRecv,
64+
Chan: reflect.ValueOf(ch),
65+
})
66+
}
67+
68+
if withDefault {
69+
cases = append(cases, reflect.SelectCase{
70+
Dir: reflect.SelectDefault,
71+
Chan: reflect.Value{},
72+
Send: reflect.Value{},
73+
})
74+
}
75+
76+
return cases
77+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module demo
2+
3+
go 1.19
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"math/rand"
6+
"reflect"
7+
"sync"
8+
"time"
9+
)
10+
11+
func main() {
12+
var wg sync.WaitGroup
13+
wg.Add(2)
14+
var rchs []chan int
15+
for i := 0; i < 10; i++ {
16+
rchs = append(rchs, make(chan int))
17+
}
18+
19+
// 创建SelectCase
20+
var cases = createRecvCases(rchs)
21+
22+
// 消费者goroutine
23+
go func() {
24+
defer wg.Done()
25+
for {
26+
chosen, recv, ok := reflect.Select(cases)
27+
if ok {
28+
fmt.Printf("recv from channel [%d], val=%v\n", chosen, recv)
29+
continue
30+
}
31+
// one of the channels is closed, exit the goroutine
32+
fmt.Printf("channel [%d] closed, select goroutine exit\n", chosen)
33+
return
34+
}
35+
}()
36+
37+
// 生产者goroutine
38+
go func() {
39+
defer wg.Done()
40+
var n int
41+
s := rand.NewSource(time.Now().Unix())
42+
r := rand.New(s)
43+
for i := 0; i < 10; i++ {
44+
n = r.Intn(10)
45+
rchs[n] <- n
46+
}
47+
close(rchs[n])
48+
}()
49+
50+
wg.Wait()
51+
}
52+
53+
func createRecvCases(rchs []chan int) []reflect.SelectCase {
54+
var cases []reflect.SelectCase
55+
56+
// 创建recv case
57+
for _, ch := range rchs {
58+
cases = append(cases, reflect.SelectCase{
59+
Dir: reflect.SelectRecv,
60+
Chan: reflect.ValueOf(ch),
61+
})
62+
}
63+
return cases
64+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module demo
2+
3+
go 1.19
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
"sync"
7+
)
8+
9+
func main() {
10+
var wg sync.WaitGroup
11+
wg.Add(2)
12+
ch0, ch1, ch2 := make(chan int), make(chan int), make(chan int)
13+
var schs = []chan int{ch0, ch1, ch2}
14+
15+
// 创建SelectCase
16+
var cases = createCases(schs)
17+
18+
// 生产者goroutine
19+
go func() {
20+
defer wg.Done()
21+
for range cases {
22+
chosen, _, _ := reflect.Select(cases)
23+
fmt.Printf("send to channel [%d], val=%v\n", chosen, cases[chosen].Send)
24+
cases[chosen].Chan = reflect.Value{}
25+
}
26+
fmt.Println("select goroutine exit")
27+
return
28+
}()
29+
30+
// 消费者goroutine
31+
go func() {
32+
defer wg.Done()
33+
for range schs {
34+
var v int
35+
select {
36+
case v = <-ch0:
37+
fmt.Printf("recv %d from ch0\n", v)
38+
case v = <-ch1:
39+
fmt.Printf("recv %d from ch1\n", v)
40+
case v = <-ch2:
41+
fmt.Printf("recv %d from ch2\n", v)
42+
}
43+
}
44+
}()
45+
46+
wg.Wait()
47+
}
48+
49+
func createCases(schs []chan int) []reflect.SelectCase {
50+
var cases []reflect.SelectCase
51+
52+
// 创建send case
53+
for i, ch := range schs {
54+
n := i + 100
55+
cases = append(cases, reflect.SelectCase{
56+
Dir: reflect.SelectSend,
57+
Chan: reflect.ValueOf(ch),
58+
Send: reflect.ValueOf(n),
59+
})
60+
}
61+
62+
return cases
63+
}

0 commit comments

Comments
 (0)