package main import ( "runtime" "sync" "sync/atomic" "time" ) var wg sync.WaitGroup type intchan chan int func main() { ch := make(chan int, 2) ch <- 1 println("len, cap of channel:", len(ch), cap(ch), ch == nil) ch = make(chan int) println("len, cap of channel:", len(ch), cap(ch), ch == nil) wg.Add(1) go sender(ch) n, ok := <-ch println("recv from open channel:", n, ok) for n := range ch { println("received num:", n) } wg.Wait() n, ok = <-ch println("recv from closed channel:", n, ok) // Test various channel size types. _ = make(chan int, int8(2)) _ = make(chan int, int16(2)) _ = make(chan int, int32(2)) _ = make(chan int, int64(2)) _ = make(chan int, uint8(2)) _ = make(chan int, uint16(2)) _ = make(chan int, uint32(2)) _ = make(chan int, uint64(2)) // Test that named channels don't crash the compiler. named := make(intchan, 1) named <- 3 <-named select { case <-named: default: } // Test bigger values ch2 := make(chan complex128) wg.Add(1) go sendComplex(ch2) println("complex128:", <-ch2) wg.Wait() // Test multi-sender. ch = make(chan int) wg.Add(3) go fastsender(ch, 10) go fastsender(ch, 23) go fastsender(ch, 40) slowreceiver(ch) wg.Wait() // Test multi-receiver. ch = make(chan int) wg.Add(3) var result atomic.Uint32 go fastreceiveradd(ch, &result) go fastreceiveradd(ch, &result) go fastreceiveradd(ch, &result) slowsender(ch) wg.Wait() println("sum of sums:", result.Load()) // Test iterator style channel. ch = make(chan int) wg.Add(1) go iterator(ch, 100) sum := 0 for i := range ch { sum += i } wg.Wait() println("sum(100):", sum) // Test simple selects. wg.Add(1) go selectDeadlock() wg.Wait() wg.Add(1) go selectNoOp() wg.Wait() // Test select with a single send operation (transformed into chan send). ch = make(chan int) wg.Add(1) go fastreceiver(ch) select { case ch <- 5: } close(ch) wg.Wait() println("did send one") // Test select with a single recv operation (transformed into chan recv). select { case n := <-ch: println("select one n:", n) } // Test select recv with channel that has one entry. ch = make(chan int) wg.Add(1) go func(ch chan int) { runtime.Gosched() ch <- 55 wg.Done() }(ch) select { case make(chan int) <- 3: println("unreachable") case <-(chan int)(nil): println("unreachable") case n := <-ch: println("select n from chan:", n) case n := <-make(chan int): println("unreachable:", n) } wg.Wait() // Test select recv with closed channel. close(ch) select { case make(chan int) <- 3: println("unreachable") case n := <-ch: println("select n from closed chan:", n) case n := <-make(chan int): println("unreachable:", n) } // Test select send. ch = make(chan int) wg.Add(1) go fastreceiver(ch) select { case ch <- 235: println("select send") case n := <-make(chan int): println("unreachable:", n) } close(ch) wg.Wait() // test non-concurrent buffered channels ch = make(chan int, 2) ch <- 1 ch <- 2 println("non-concurrent channel receive:", <-ch) println("non-concurrent channel receive:", <-ch) // test closing channels with buffered data ch <- 3 ch <- 4 close(ch) println("closed buffered channel receive:", <-ch) println("closed buffered channel receive:", <-ch) println("closed buffered channel receive:", <-ch) // test using buffered channels as regular channels with special properties wg.Add(6) ch = make(chan int, 2) go send(ch) go send(ch) go send(ch) go send(ch) go receive(ch) go receive(ch) wg.Wait() close(ch) var count int for range ch { count++ } println("hybrid buffered channel receive:", count) // test blocking selects ch = make(chan int) sch1 := make(chan int) sch2 := make(chan int) sch3 := make(chan int) wg.Add(3) go func() { defer wg.Done() time.Sleep(time.Millisecond) sch1 <- 1 }() go func() { defer wg.Done() time.Sleep(time.Millisecond) sch2 <- 2 }() go func() { defer wg.Done() // merge sch2 and sch3 into ch for i := 0; i < 2; i++ { var v int select { case v = <-sch1: case v = <-sch2: } select { case sch3 <- v: panic("sent to unused channel") case ch <- v: } } }() sum = 0 for i := 0; i < 2; i++ { select { case sch3 <- sum: panic("sent to unused channel") case v := <-ch: sum += v } } wg.Wait() println("blocking select sum:", sum) } func send(ch chan<- int) { ch <- 1 wg.Done() } func receive(ch <-chan int) { <-ch wg.Done() } func sender(ch chan int) { for i := 1; i <= 8; i++ { if i == 4 { time.Sleep(time.Millisecond) println("slept") } ch <- i } close(ch) wg.Done() } func sendComplex(ch chan complex128) { ch <- 7 + 10.5i wg.Done() } func fastsender(ch chan int, n int) { ch <- n ch <- n + 1 wg.Done() } func slowreceiver(ch chan int) { sum := 0 for i := 0; i < 6; i++ { sum += <-ch time.Sleep(time.Microsecond) } println("sum of n:", sum) } func slowsender(ch chan int) { for n := 0; n < 6; n++ { time.Sleep(time.Microsecond) ch <- 12 + n } } func fastreceiver(ch chan int) { sum := 0 for i := 0; i < 2; i++ { n := <-ch sum += n } println("sum:", sum) wg.Done() } func fastreceiveradd(ch chan int, result *atomic.Uint32) { sum := 0 for i := 0; i < 2; i++ { n := <-ch sum += n } result.Add(uint32(sum)) wg.Done() } func iterator(ch chan int, top int) { for i := 0; i < top; i++ { ch <- i } close(ch) wg.Done() } func selectDeadlock() { println("deadlocking") wg.Done() select {} println("unreachable") } func selectNoOp() { println("select no-op") select { default: } println("after no-op") wg.Done() }