github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/testdata/channel.go (about) 1 package main 2 3 import ( 4 "runtime" 5 "sync" 6 "time" 7 ) 8 9 var wg sync.WaitGroup 10 11 type intchan chan int 12 13 func main() { 14 ch := make(chan int, 2) 15 ch <- 1 16 println("len, cap of channel:", len(ch), cap(ch), ch == nil) 17 18 ch = make(chan int) 19 println("len, cap of channel:", len(ch), cap(ch), ch == nil) 20 21 wg.Add(1) 22 go sender(ch) 23 24 n, ok := <-ch 25 println("recv from open channel:", n, ok) 26 27 for n := range ch { 28 println("received num:", n) 29 } 30 31 wg.Wait() 32 n, ok = <-ch 33 println("recv from closed channel:", n, ok) 34 35 // Test various channel size types. 36 _ = make(chan int, int8(2)) 37 _ = make(chan int, int16(2)) 38 _ = make(chan int, int32(2)) 39 _ = make(chan int, int64(2)) 40 _ = make(chan int, uint8(2)) 41 _ = make(chan int, uint16(2)) 42 _ = make(chan int, uint32(2)) 43 _ = make(chan int, uint64(2)) 44 45 // Test that named channels don't crash the compiler. 46 named := make(intchan, 1) 47 named <- 3 48 <-named 49 select { 50 case <-named: 51 default: 52 } 53 54 // Test bigger values 55 ch2 := make(chan complex128) 56 wg.Add(1) 57 go sendComplex(ch2) 58 println("complex128:", <-ch2) 59 wg.Wait() 60 61 // Test multi-sender. 62 ch = make(chan int) 63 wg.Add(3) 64 go fastsender(ch, 10) 65 go fastsender(ch, 23) 66 go fastsender(ch, 40) 67 slowreceiver(ch) 68 wg.Wait() 69 70 // Test multi-receiver. 71 ch = make(chan int) 72 wg.Add(3) 73 go fastreceiver(ch) 74 go fastreceiver(ch) 75 go fastreceiver(ch) 76 slowsender(ch) 77 wg.Wait() 78 79 // Test iterator style channel. 80 ch = make(chan int) 81 wg.Add(1) 82 go iterator(ch, 100) 83 sum := 0 84 for i := range ch { 85 sum += i 86 } 87 wg.Wait() 88 println("sum(100):", sum) 89 90 // Test simple selects. 91 go selectDeadlock() // cannot use waitGroup here - never terminates 92 wg.Add(1) 93 go selectNoOp() 94 wg.Wait() 95 96 // Test select with a single send operation (transformed into chan send). 97 ch = make(chan int) 98 wg.Add(1) 99 go fastreceiver(ch) 100 select { 101 case ch <- 5: 102 } 103 close(ch) 104 wg.Wait() 105 println("did send one") 106 107 // Test select with a single recv operation (transformed into chan recv). 108 select { 109 case n := <-ch: 110 println("select one n:", n) 111 } 112 113 // Test select recv with channel that has one entry. 114 ch = make(chan int) 115 wg.Add(1) 116 go func(ch chan int) { 117 runtime.Gosched() 118 ch <- 55 119 wg.Done() 120 }(ch) 121 select { 122 case make(chan int) <- 3: 123 println("unreachable") 124 case <-(chan int)(nil): 125 println("unreachable") 126 case n := <-ch: 127 println("select n from chan:", n) 128 case n := <-make(chan int): 129 println("unreachable:", n) 130 } 131 wg.Wait() 132 133 // Test select recv with closed channel. 134 close(ch) 135 select { 136 case make(chan int) <- 3: 137 println("unreachable") 138 case n := <-ch: 139 println("select n from closed chan:", n) 140 case n := <-make(chan int): 141 println("unreachable:", n) 142 } 143 144 // Test select send. 145 ch = make(chan int) 146 wg.Add(1) 147 go fastreceiver(ch) 148 select { 149 case ch <- 235: 150 println("select send") 151 case n := <-make(chan int): 152 println("unreachable:", n) 153 } 154 close(ch) 155 wg.Wait() 156 157 // test non-concurrent buffered channels 158 ch = make(chan int, 2) 159 ch <- 1 160 ch <- 2 161 println("non-concurrent channel receive:", <-ch) 162 println("non-concurrent channel receive:", <-ch) 163 164 // test closing channels with buffered data 165 ch <- 3 166 ch <- 4 167 close(ch) 168 println("closed buffered channel receive:", <-ch) 169 println("closed buffered channel receive:", <-ch) 170 println("closed buffered channel receive:", <-ch) 171 172 // test using buffered channels as regular channels with special properties 173 wg.Add(6) 174 ch = make(chan int, 2) 175 go send(ch) 176 go send(ch) 177 go send(ch) 178 go send(ch) 179 go receive(ch) 180 go receive(ch) 181 wg.Wait() 182 close(ch) 183 var count int 184 for range ch { 185 count++ 186 } 187 println("hybrid buffered channel receive:", count) 188 189 // test blocking selects 190 ch = make(chan int) 191 sch1 := make(chan int) 192 sch2 := make(chan int) 193 sch3 := make(chan int) 194 wg.Add(3) 195 go func() { 196 defer wg.Done() 197 time.Sleep(time.Millisecond) 198 sch1 <- 1 199 }() 200 go func() { 201 defer wg.Done() 202 time.Sleep(time.Millisecond) 203 sch2 <- 2 204 }() 205 go func() { 206 defer wg.Done() 207 // merge sch2 and sch3 into ch 208 for i := 0; i < 2; i++ { 209 var v int 210 select { 211 case v = <-sch1: 212 case v = <-sch2: 213 } 214 select { 215 case sch3 <- v: 216 panic("sent to unused channel") 217 case ch <- v: 218 } 219 } 220 }() 221 sum = 0 222 for i := 0; i < 2; i++ { 223 select { 224 case sch3 <- sum: 225 panic("sent to unused channel") 226 case v := <-ch: 227 sum += v 228 } 229 } 230 wg.Wait() 231 println("blocking select sum:", sum) 232 } 233 234 func send(ch chan<- int) { 235 ch <- 1 236 wg.Done() 237 } 238 239 func receive(ch <-chan int) { 240 <-ch 241 wg.Done() 242 } 243 244 func sender(ch chan int) { 245 for i := 1; i <= 8; i++ { 246 if i == 4 { 247 time.Sleep(time.Microsecond) 248 println("slept") 249 } 250 ch <- i 251 } 252 close(ch) 253 wg.Done() 254 } 255 256 func sendComplex(ch chan complex128) { 257 ch <- 7 + 10.5i 258 wg.Done() 259 } 260 261 func fastsender(ch chan int, n int) { 262 ch <- n 263 ch <- n + 1 264 wg.Done() 265 } 266 267 func slowreceiver(ch chan int) { 268 sum := 0 269 for i := 0; i < 6; i++ { 270 sum += <-ch 271 time.Sleep(time.Microsecond) 272 } 273 println("sum of n:", sum) 274 } 275 276 func slowsender(ch chan int) { 277 for n := 0; n < 6; n++ { 278 time.Sleep(time.Microsecond) 279 ch <- 12 + n 280 } 281 } 282 283 func fastreceiver(ch chan int) { 284 sum := 0 285 for i := 0; i < 2; i++ { 286 n := <-ch 287 sum += n 288 } 289 println("sum:", sum) 290 wg.Done() 291 } 292 293 func iterator(ch chan int, top int) { 294 for i := 0; i < top; i++ { 295 ch <- i 296 } 297 close(ch) 298 wg.Done() 299 } 300 301 func selectDeadlock() { 302 println("deadlocking") 303 select {} 304 println("unreachable") 305 } 306 307 func selectNoOp() { 308 println("select no-op") 309 select { 310 default: 311 } 312 println("after no-op") 313 wg.Done() 314 }