package main import ( "fmt" "sync" "time" "unsafe" ) func main10() { done := make(chan struct{}) // 結束事件 c := make(chan string) // 數據傳輸通道 go func() { s := <-c // 接受消息 println(s) close(done) // 關閉通道,做爲結束通知 }() c <- "hi!" // 發送消息 <-done // 阻塞,直到有數據或者管道關閉 } func main11() { c := make(chan int, 3) // 建立帶 3 個緩衝槽的異步通道 c <- 1 // 緩衝區未滿,不會阻塞 c <- 2 println(<-c) // 緩衝區尚有數據,不會阻塞 println(<-c) } // 緩衝區大小是內部屬性,不屬於類型組成部分。另外通道變量自己就是指針,能夠用相等操做符判斷是否爲同一對象或者nil func main12() { var a, b chan int = make(chan int, 3), make(chan int) var c chan bool println(a == b) println(c == nil) fmt.Printf("%p, %d\n", a, unsafe.Sizeof(a)) } // 對於同步通道 len() 和 cap() 都返回0 func main13() { a, b := make(chan int), make(chan int, 3) b <- 1 b <- 2 println("a:", len(a), cap(a)) println("b:", len(b), cap(b)) } func main14() { c := make(chan int) go func() { defer close(c) // 關閉通道 println("sub ....") }() <-c // 阻塞直到通道關閉 print("main ....") } func main15() { done := make(chan struct{}) c := make(chan int) go func() { defer close(done) //for { // x, ok := <-c // if !ok { // return // } // // println(x) //} for x := range c { // 循環獲取消息,直到通道被關閉 println(x) } }() c <- 1 c <- 2 c <- 3 close(c) <-done } // 通知能夠是羣體性的 func main16() { var wg sync.WaitGroup ready := make(chan struct{}) for i := 0; i < 3; i++ { wg.Add(1) go func(id int) { defer wg.Done() println(id, ": ready") <-ready println(id, ": running...") }(i) } time.Sleep(time.Second) println("Ready? Go!") close(ready) wg.Wait() } func main17() { c := make(chan int, 3) c <- 1 c <- 2 close(c) for i := 0; i < cap(c)+1; i++ { x, ok := <-c println(i, ":", ok, x) } } // 單向通道,close不能用於接收端,不可逆 func main18() { var wg sync.WaitGroup wg.Add(2) c := make(chan int) var send chan<- int = c var recv <-chan int = c go func() { defer wg.Done() for x := range recv { println(x) } }() go func() { defer wg.Done() defer close(c) for i := 0; i < 5; i++ { send <- i } }() wg.Wait() } // select 同時處理多個通道,它會隨機選擇一個可用通道作收發操做 // 若是要等到所有通道消息處理結束,可將已完成通道設置爲 nil. 這樣它就會被阻塞,再也不被選select選中 func main19() { var wg sync.WaitGroup wg.Add(3) a, b := make(chan int), make(chan int) go func() { defer wg.Done() for { var ( x int ok bool ) select { // 隨機選擇可用 channel 接收數據 case x, ok = <-a: if !ok { a = nil break } println("a", x) case x, ok = <-b: if !ok { b = nil break } println("b", x) } if a == nil && b == nil { // 所有結束,退出循環 return } } }() go func() { defer wg.Done() defer close(a) for i := 0; i < 3; i++ { //select { // 隨機選擇發送 channel //case a <- i: //case b <- i * 10: //} a <- i } }() go func() { defer wg.Done() defer close(b) for i := 0; i < 5; i++ { b <- i * 10 } }() wg.Wait() } func main20() { done := make(chan int) c := make(chan int) go func() { defer close(done) for { select { case x, ok := <- c: if !ok { return } fmt.Println("data:", x) default: // 避免select阻塞 } fmt.Println(time.Now()) time.Sleep(time.Second) } }() time.Sleep(time.Second * 5) c <- 100 close(c) <-done } func main21() { done := make(chan struct{}) data := []chan int { make(chan int, 3), } go func() { defer close(done) for i := 0; i < 10; i++ { select { case data[len(data) - 1] <- i: default: data = append(data, make(chan int, 3)) } } }() <-done for i := 0; i < len(data); i++ { c := data[i] close(c) for x := range c { println(x) } } } type receiver struct { sync.WaitGroup data chan int } func newReceiver() *receiver { r := &receiver{ data: make(chan int), } r.Add(1) go func() { defer r.Done() for x := range r.data { // 接收消息,直到通道關閉 println("recv:", x) } }() return r } func main22() { r := newReceiver() r.data <- 1 r.data <- 2 r.data <- 1 r.data <- 2 r.data <- 1 r.data <- 2 close(r.data) r.Wait() } type pool chan []byte func newPool(cap int) pool { return make(chan []byte, cap) } func (p pool) get() []byte { var v []byte select { case v = <- p: default: v = make([]byte, 10) } return v } func (p pool) put(b []byte) { select { case p <- b: default: } }