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:
}
}
有疑问加站长微信联系(非本文作者)