关闭chanel
发送者这边可以发送一个close(ch)
,接收方收到之后就知道发送方之后都不会再发送信息了。
接收者这边可以通过一个额外的变量,检测通道是否已经关闭。类似这样:v, ok := <- ch
这里的ok为false就代表我们从一个已经关闭的chanel获取数据,这个数据是chanel类型对应的零值。
例如:
package main
import (
"fmt"
"time"
)
func main() {
// 子协程:写10个数据,每写一次,就阻塞一次,主协程读取一次,阻塞解除一次
// 主协程:读取一次数据,阻塞一次,子协程写一次,阻塞解除一次
ch1 := make(chan int)
go sendData(ch1)
//读取chanel中的数据,不过由于我们可能不知道发送方发送了多少数据, 这里用死循环
for {
time.Sleep(1 * time.Second)
v, ok := <-ch1
if !ok {
fmt.Println("all the data has bean read ", ok)
break
}
fmt.Println("the data read is: ", v, ok)
}
}
func sendData(ch1 chan int) {
// 发送方: 发送10条数据
for i := 0; i < 10; i++ {
//把i写入chanel
ch1 <- i
}
//关闭ch1通道
close(ch1)
}
运行结果是:
the data read is: 0 true
the data read is: 1 true
the data read is: 2 true
the data read is: 3 true
the data read is: 4 true
the data read is: 5 true
the data read is: 6 true
the data read is: 7 true
the data read is: 8 true
the data read is: 9 true
all the data has bean read false
chanel的range循环
相对于上面的for 用range能够省去对ok值的判断,更加简洁方便地操作chanel。
下面这个例子中,range的含义就是从通道ch1中读取数据并且赋值给v:
package main
import (
"fmt"
"time"
)
func main() {
// 子协程:写10个数据,每写一次,就阻塞一次,主协程读取一次,阻塞解除一次
// 主协程:读取一次数据,阻塞一次,子协程写一次,阻塞解除一次
ch1 := make(chan int)
go sendData(ch1)
//读取chanel中的数据,不过由于我们可能不知道发送方发送了多少数据, 这里用死循环
for v := range ch1 { //这里range的含义就是从通道ch1中读取数据并且赋值给v [v<- ch1]
fmt.Println("reading data: ", v)
}
fmt.Println("main-goroutine completed")
}
func sendData(ch1 chan int) {
// 发送方: 发送10条数据
for i := 0; i < 10; i++ {
time.Sleep(1 * time.Second)
//把i写入chanel
ch1 <- i
}
//关闭ch1通道
close(ch1)
}
运行结果是:
reading data: 0
reading data: 1
reading data: 2
reading data: 3
reading data: 4
reading data: 5
reading data: 6
reading data: 7
reading data: 8
reading data: 9
main-goroutine completed
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。