golang语言 并发
main goroutine返回时,所有goroutine都会被直接打断,程序退出
go f(x,y),f、x、y的求值发生在当前goroutine中,f的执行发生在新goroutine中
goroutine运行在相同的地址空间中,访问共享内存需要同步
未初始化的channel类型变量的值为nil,在nil信道上进行发送、接收、range,将永远阻塞
make可创建初始化的channel,并接受一个可选的容量参数,
channel会引用make创建的底层数据结构,复制的新channel会引用相同的底层数据结构
channel是先进先出的
无缓存的channel,接收者收到数据发生在唤醒发送者goroutine之前
make(chan int, 100)
chan<- chan int // 等价于 chan<- (chan int)
chan<- <-chan int // 等价于 chan<- (<-chan int)
<-chan <-chan int // 等价于 <-chan (<-chan int)
chan (<-chan int)
close
内建函数 close(c) 标明不再有值会在信道c上发送。
关闭channel可以起到广播的作用
向已关闭的信道上发送会引发panic。
重复关闭channel或者关闭nil值的channel会抛出panic,关闭一个只接收的channel会引发编译错误
关闭channel时,如果该channel的发送goroutine队列不为空,那么这些goroutine将panic
在已关闭的信道上接收,可以接收到之前已成功发送的数据,如果信道里已经没有数据了,那么会立即产生一个零值的数据。可以用x,ok := <-c的形式,判断c是否被关闭
range c 会在c被关闭后结束循环。
当一个channel不被引用时,无论它是否被关闭,都会被垃圾回收。
select
最多有一个default,可以在任何位置,没有初始化语句,不能fallthrough
多个case就绪,随机选择一个。
没有case就绪,且没有default,将永远阻塞
所有channel都是nil值,且没有default,将永远阻塞
没有case,select { } 永远阻塞
select {
case <-ch1:
// ...
case x := <-ch2:
// ...use x...
case ch3 <- y:
// ...
default:
// ...
}
channel的方向
chan T // 可以被用来发送和接收类型T的值 chan<- float64 // 只能被用来发送浮点数 <-chan int // 只能被用来接收整数
双向的channel可以赋值给单向的channel,此时会做一个隐式类型转换。单向不能赋值给双向
chan<- 和 <-chan 也不能相互转换
for {
select {
case d := <-ch: // ch阻塞时会不停地循环
default:
}
}
for {
select {
case d := <-ch: // ch被关闭时会不停地循环
}
}
x, y := <-c, <-c