協程間通信的普通使用, 發送值給channel
, 外部channel
接收.bash
func t1() {
ch := make(chan int)
go func() {
ch <- 1
}()
// <-ch // 致使下面語句阻塞
fmt.Println("channel int", <-ch)
}
複製代碼
channel int 1
複製代碼
channel
支持緩衝區ui
func t2() {
ch := make(chan int, 3)
go func() {
ch <- 1
ch <- 2
ch <- 3
ch <- 4 // 會阻塞寫不入, 除非ch已接收
close(ch) // 關閉後不能再寫入, 而且緩衝區內爲空時則返回零值
}()
fmt.Println("buffer channel int",
<-ch,
<-ch,
<-ch,
<-ch,
<-ch)
}
複製代碼
buffer channel int 1 2 3 4 0
複製代碼
select
是專門給管道定製spa
func t3() {
ch1 := make(chan int)
ch2 := make(chan struct{})
go func() {
ch1 <- 2
}()
select {
case <-ch1:
fmt.Println("select here is ch1")
case <-ch2:
fmt.Println("select here is ch2")
}
}
複製代碼
select here is ch1
複製代碼
使用for
設計
func t4() {
ch := make(chan int, 5)
go func() {
for i:=1; i<=5; i++ {
time.Sleep(time.Millisecond * 10)
ch <- i
}
}()
for v := range ch { // 會阻塞
fmt.Println("for channel ", v)
if v == 5 {
break
}
}
}
複製代碼
for channel 1
for channel 2
for channel 3
for channel 4
for channel 5
複製代碼
同時使用select
和for
3d
func t5() {
chPrint := make(chan struct{})
chStop := make(chan struct{})
go func(){
time.Sleep(time.Second * 1)
chPrint <- struct{}{}
time.Sleep(time.Second * 1)
chPrint <- struct{}{}
time.Sleep(time.Second * 1)
chStop <- struct{}{}
}()
var sum int
for {
time.Sleep(time.Millisecond)
select {
case <-chPrint:
fmt.Println("for+select now is", sum)
case <-chStop:
fmt.Println("for+select stop, result is", sum)
return
default:
if sum == 10000 {
fmt.Println("for+select end, result is", sum)
return
}
sum += 1
}
}
}
複製代碼
for+select now is 766
for+select now is 1540
for+select stop, result is 2309
複製代碼
判斷管道是否關閉code
func t6() {
ch := make(chan struct{})
go func() {
close(ch)
//ch <- struct{}{} // 只運行這句, 輸出OK
}()
if _, ok := <-ch; ok {
fmt.Println("if channel is ok")
return
}
fmt.Println("if channel is bad")
}
複製代碼
if channel is bad
複製代碼
以只發送或只接收爲傳遞參數, 同理也能夠爲返回值cdn
func t7() {
ch := make(chan struct{})
chExit := make(chan struct{})
go func(chRecv <-chan struct{}) {
fmt.Println("recv channel")
<-chRecv
chExit<- struct{}{}
}(ch)
go func(chSend chan<- struct{}) {
fmt.Println("send channel")
chSend <- struct{}{}
}(ch)
<-chExit
}
複製代碼
send channel
recv channel
複製代碼
makechan()
初始化hchan
結構體, 若是沒有緩衝區即分配hchanSize
大小的內存並返回;而有緩衝區的狀況下, 則計算管道元素類型大小並分配hchanSize
+(elem.size
* size
)大小的內存(緩衝區是一個環形的結構設計), 最後返回hchan
. 協程
chansend()
向channel
發送數據, 首先鎖住當前協程, 有以下幾種狀況, 按順序判斷:blog
chanrecv()
接收channel
的數據, 首先鎖住當前協程, 有以下幾種狀況, 按順序判斷:隊列
channel
關閉並無緩衝數據, 接收者接收的值將會是零值, 釋放鎖並退出.chansend
差很少, 多了個已關閉並無緩衝數據的判斷.
closechan
關閉channel
, 首先也要獲取鎖, 關閉管道並釋放全部接收和發送的隊列並清醒全部sudog. 但緩衝區的數據不會清理, 隨時等待被接收.