-
Notifications
You must be signed in to change notification settings - Fork 41
/
go_chan.go
121 lines (101 loc) · 2.16 KB
/
go_chan.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main
import (
"fmt"
"time"
)
func main() {
go fmt.Println("goroutine")
fmt.Println("main")
for i := 0; i < 3; i++ {
// Fix 2: Use a loop body variable
i := i // "i" shadows "i" from the for loop
go func() {
fmt.Println(i) // i from line 14
}()
/* Fix 1: Use a parameter
go func(n int) {
fmt.Println(n)
}(i)
*/
/* BUG: All goroutines use the "i" for the for loop
go func() {
fmt.Println(i) // i from line 12
}()
*/
}
time.Sleep(10 * time.Millisecond)
shadowExample()
ch := make(chan string)
go func() {
ch <- "hi" // send
}()
msg := <-ch // receive
fmt.Println(msg)
go func() {
for i := 0; i < 3; i++ {
msg := fmt.Sprintf("message #%d", i+1)
ch <- msg
}
close(ch)
}()
for msg := range ch {
fmt.Println("got:", msg)
}
/* for/range does this
for {
msg, ok := <-ch
if !ok {
break
}
fmt.Println("got:", msg)
}
*/
msg = <-ch // ch is closed
fmt.Printf("closed: %#v\n", msg)
msg, ok := <-ch // ch is closed
fmt.Printf("closed: %#v (ok=%v)\n", msg, ok)
// ch <- "hi" // ch is closed -> panic
values := []int{15, 8, 42, 16, 4, 23}
fmt.Println(sleepSort(values))
}
/*
For every value "n" in values, spin a goroutine that will
- sleep "n" milliseconds
- Send "n" over a channel
In the function body, collect values from the channel to a slice and return it.
*/
func sleepSort(values []int) []int {
ch := make(chan int)
for _, n := range values {
n := n
go func() {
time.Sleep(time.Duration(n) * time.Millisecond)
ch <- n
}()
}
var out []int
// for i := 0; i < len(values); i++ {
for range values {
n := <-ch
out = append(out, n)
}
return out
}
/* Channel semantics
- send & receive will block until opposite operation (*)
- Buffered channel has cap(ch) non-blocking sends
- receive from a closed channel will return the zero value without blocking
- send to a closed channel will panic
- closing a closed channel will panic
- send/receive to a nil channel will block forever
See also https://www.353solutions.com/channel-semantics
*/
func shadowExample() {
n := 7
{
n := 2 // from here to } this is "n"
// n = 2 // outer n
fmt.Println("inner", n)
}
fmt.Println("outer", n)
}