package main
import (
"fmt"
"time"
)
// 子goroutine,主goroutine结束,子也结束
func NewTask() {
i := 0
for {
i++
fmt.Println("new Goroutine: i =", i)
time.Sleep(1 * time.Second)
}
}
func main() {
//定义一个无缓冲的channel
c := make(chan int)
go func() {
defer fmt.Println("go goroutine 结束")
fmt.Println("go goroutine 正在进行....")
c <- 66 // 将66写的chan中
}()
// 从channel中读取数据,复制给num
num := <-c
fmt.Println("num is ", num)
}
// 结果:
go goroutine 正在进行....
go goroutine 结束
num is 66
注意:
- 有没有可能main方法先执行完,sub go还没发送给c信息?
不会,当main从chan中拿不到数据,会阻塞等待
- sub go把66放到chan中,main还没来得及读,defer会执行吗?
2.有缓冲Channel不会,因为是无缓冲channel,子sub go会阻塞等待main 获取数据
package main
import (
"fmt"
"time"
)
// 子goroutine,主goroutine结束,子也结束
func NewTask() {
i := 0
for {
i++
fmt.Println("new Goroutine: i =", i)
time.Sleep(1 * time.Second)
}
}
func main() {
//定义一个有缓冲的channel
c := make(chan int, 3)
fmt.Println("c的length =", len(c), "c的cap =", cap(c))
go func() {
defer fmt.Println("go goroutine 结束")
for i := 0; i < 4; i++ {
c <- i // 将i写的chan中
fmt.Println("go goroutine 正在进行....,发送的元素:", i, "length =", len(c), "cap = ", cap(c))
}
}()
time.Sleep(3 * time.Second)
// 从channel中读取数据,复制给num
for i := 0; i < 3; i++ {
num := <-c
fmt.Println("num is ", num)
}
fmt.Println("main 结束 ")
}
// 结果:
go goroutine 正在进行....,发送的元素: 0 length = 1 cap = 3
go goroutine 正在进行....,发送的元素: 1 length = 2 cap = 3
go goroutine 正在进行....,发送的元素: 2 length = 3 cap = 3
num is 0
num is 1
num is 2
main 结束
go goroutine 正在进行....,发送的元素: 3 length = 3 cap = 3
go goroutine 结束
注意:
- 当go goroutine中channel的元素满了,将会被阻塞,直到获取完一个num即继续运行
- 当channel为空,从里面取数据也会阻塞
- 关闭channel不用像关闭文件一样,经常去关闭
- 关闭channel后无法再向channel中发送数据(引发panic error)
- 关闭channel后,可以继续从channel中获取数据
- 对于nil channel,一定发送阻塞错误,记住一定要make
感觉兴趣的小伙伴可以加好友一起交流!!
for data := range c {
fmt.Println(data)
}
5.Channel与select的使用
单个流程下go只能监控一个Channel状态,select可以完成多个Channel监控状态
package main
import (
"fmt"
)
func feibonicii(c, quit chan int) {
x, y := 1, 1
for {
select {
case c <- x: //如果c可写,将x写入c中
x = y
y = x + y
case <-quit: // 如果quit可读,则sub go已执行完任务
fmt.Println("quit....")
return
}
}
}
func main() {
c := make(chan int)
quit := make(chan int)
// sub go
go func() {
for i := 0; i < 16; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
// main go
feibonicii(c, quit)
}