Go 语言高性能编程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func do(taskCh chan int) {
for {
select {
case t := <-taskCh:
time.Sleep(time.Millisecond)
fmt.Printf("task %d is done\n", t)
}
}
}

func sendTasks() {
taskCh := make(chan int, 10)
go do(taskCh)
for i := 0; i < 1000; i++ {
taskCh <- i
}
}

func TestDo(t *testing.T) {
t.Log(runtime.NumGoroutine())
sendTasks()
time.Sleep(time.Second)
t.Log(runtime.NumGoroutine())
}
1
2
3
4
$ go test . -v
--- PASS: TestDo (2.34s)
exit_test.go:29: 2
exit_test.go:32: 3
1
2
ch := make(chan int) // 不带缓冲区
ch := make(chan int, 10) // 带缓冲区,缓冲区满之前,即使没有接收方,发送方不阻塞
1
close(ch)
1
ch <- v
1
2
<-ch // 忽略接收值
v := <-ch // 接收值并赋值给变量 v
1
v, beforeClosed := <-ch
1
2
len(ch)
cap(ch)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func doCheckClose(taskCh chan int) {
for {
select {
case t, beforeClosed := <-taskCh:
if !beforeClosed {
fmt.Println("taskCh has been closed")
return
}
time.Sleep(time.Millisecond)
fmt.Printf("task %d is done\n", t)
}
}
}

func sendTasksCheckClose() {
taskCh := make(chan int, 10)
go doCheckClose(taskCh)
for i := 0; i < 1000; i++ {
taskCh <- i
}
close(taskCh)
}

func TestDoCheckClose(t *testing.T) {
t.Log(runtime.NumGoroutine())
sendTasksCheckClose()
time.Sleep(time.Second)
runtime.GC()
t.Log(runtime.NumGoroutine())
}
1
2
3
4
5
6
$ go test -run=TestDoCheckClose -v
task 999 is done
taskCh has been closed
--- PASS: TestDoCheckClose (2.34s)
exit_test.go:59: 2
exit_test.go:63: 2
1
2
3
4
5
6
7
8
9
10
11
12
func SafeClose(ch chan T) (justClosed bool) {
defer func() {
if recover() != nil {
// 一个函数的返回结果可以在defer调用中修改。
justClosed = false
}
}()

// 假设ch != nil。
close(ch) // 如果 ch 已关闭,将 panic
return true // <=> justClosed = true; return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
type MyChannel struct {
C chan T
once sync.Once
}

func NewMyChannel() *MyChannel {
return &MyChannel{C: make(chan T)}
}

func (mc *MyChannel) SafeClose() {
mc.once.Do(func() {
close(mc.C)
})
}
赞赏支持

请我吃胡萝卜 =^_^=

支付宝

微信