无缓冲与有缓冲:
c1:=make(chan int) 无缓冲
c2:=make(chan int,1) 有缓冲,可存放1个值
阻塞:不管事有缓存还是无缓存,当 channel 里面放满了数据(缓存不够了,无法继续写入),就会发生阻塞。
等待:主程序下,写入 channel (写满)的时候,会等待取走数据;读取 channel(无数据)等待写入数据。
主程序与线程:如果没有 channel 的牵绊,主程序不会等待线程。
1、如果在 main 主程序下发生阻塞,就会一直等待这个 channel 被消耗(因为 写和读都完成后,才算是一个完整的 channel 动作,带有原子性)
就会报错:
package main
import (
"fmt"
)
var c chan int
func send(i int) {
fmt.Println("send -> ", i)
c <- i
}
func receive() {
fmt.Println("receive : ", <-c)
}
func main() {
count := 10
c = make(chan int)
for i := 0; i < count; i++ {
send(i)
}
for i := 0; i < count; i++ {
receive()
}
}
#go run test.go
send -> 0
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.send(0x0)
D:/Golang/Test/src/goroutine.go:11 +0xc9
main.main()
D:/Golang/Test/src/goroutine.go:23 +0x69
exit status 2#报错原因:因为写入发送了阻塞,后面的 receive() 都没机会执行。
#解决方法:使用 go send(i) 或者 设置 channel 缓存数大于等于写入数量,这时,写入的时候不会发生阻塞。
2、如果在 goroutine(线程)发生阻塞,不会占用主程序进程,也不会等待 channel 被消耗,就不会报错。
因为主程序执行完就关闭进程了,线程就没了。
当然主程序可以读取 channel,把 channel 读取出来,这个时候主程序会等待把 channel 都读完才结束程序。
个人感觉使用 goroutine 去写 channel,通过主线程读 channel 才是正确的使用姿势。
#使用 goroutine
package main
import (
"fmt"
)
var c chan int
func send(i int) {
fmt.Println("send -> ", i)
c <- i
}
func receive() {
fmt.Println("receive : ", <-c)
}
func main() {
count := 10
c = make(chan int)
for i := 0; i < count; i++ {
go send(i)
}
for i := 0; i < count; i++ {
receive()
}
}
//------输出------
E:/Go/bin/go.exe run goroutine.go [D:/Golang/Test/src]
send -> 0
receive : 0
send -> 9
receive : 9
send -> 1
receive : 1
send -> 7
receive : 7
send -> 8
receive : 8
send -> 2
receive : 2
send -> 5
receive : 5
send -> 6
receive : 6
send -> 4
receive : 4
send -> 3
receive : 3
命令退出代码 0.#增加缓存数量,不小于写入数
package main
import (
"fmt"
)
var c chan int
func send(i int) {
fmt.Println("send -> ", i)
c <- i
}
func receive() {
fmt.Println("receive : ", <-c)
}
func main() {
count := 10
c = make(chan int, 10)
for i := 0; i < count; i++ {
send(i)
}
for i := 0; i < count; i++ {
receive()
}
}
//------输出-----
E:/Go/bin/go.exe run goroutine.go [D:/Golang/Test/src]
send -> 0
send -> 1
send -> 2
send -> 3
send -> 4
send -> 5
send -> 6
send -> 7
send -> 8
send -> 9
receive : 0
receive : 1
receive : 2
receive : 3
receive : 4
receive : 5
receive : 6
receive : 7
receive : 8
receive : 9
命令退出代码 0.#主程序并未等待线程完成,就退出了,线程只执行了2次就没了。
package main
import (
"fmt"
)
var c chan int
func send(i int) {
fmt.Println("send -> ", i)
c <- i
}
func receive() {
fmt.Println("receive : ", <-c)
}
func main() {
count := 10
c = make(chan int, 10)
for i := 0; i < count; i++ {
send(i)
}
for i := 0; i < count; i++ {
go receive()
}
}
//------输出----
E:/Go/bin/go.exe run goroutine.go [D:/Golang/Test/src]
send -> 0
send -> 1
send -> 2
send -> 3
send -> 4
send -> 5
send -> 6
send -> 7
send -> 8
send -> 9
receive : 0
receive : 1
命令退出代码 0.