问题:1.在close(chan)语句后,是否直接关闭了channel。如果不是,channel何时被关闭的;
2.读取channel中的值时,若channel中无值,会阻塞后边的语句,那么通过range读取channel中的值,何时会跳出range接着执行
结论:1.channel的关闭时机:1)给channel调用close()且其中数据全部被消费结束。2)主线程关闭
2.通过range取channel中的值,如果channel一直未被关闭,则range会一直阻塞后续代码执行。只有channel被关闭,才会跳出range
代码验证:1.
package main
import "fmt"
var chans1 = make(chan int, 5)
var chans2 = make(chan int, 3)
func main() {
go func() {
for i := 0; i < 5; i++ {
chans1 <- i
fmt.Println("chans1赋值:", i)
}
close(chans1)
}()
go func() {
for i := 0; i < 2; i++ {
chans2 <- i
fmt.Println("chans2赋值:", i)
}
close(chans2)
}()
fmt.Println("main start")
for i := 0; i < 3; i++ {
<-chans1
<-chans2
}
_, ok1 := <-chans1
_, ok2 := <-chans2
fmt.Println("ok1: ", ok1)
fmt.Println("ok2: ", ok2)
fmt.Println("main end")
}
result:可知chans1,已全部赋值,但对应ok1返回true,未被关闭。chans2,已全部赋值且全部被消费,对应ok2返回false,已被关闭。
2.1)
package main
import (
"fmt"
"time"
)
var chans = make(chan int)
func main() {
go func() {
// // range会直到channel被close才会停止,停止前会阻塞后面的语句
// for v := range chans {
// fmt.Println(v)
// }
<-chans
// channel中无值,会阻塞下边语句执行。range时,会阻塞到channel关闭,再接着执行下边的语句
fmt.Println("读取channel")
}()
fmt.Println("main start...")
time.Sleep(time.Second * 2)
chans <- 2
// close(chans)
time.Sleep(time.Second * 3)
fmt.Println("main end...")
}
result:当chans未被赋值时,协程被阻塞。赋值2后,即使无close,协程在读取到chans后,会接着执行。
2)
package main
import (
"fmt"
"time"
)
var chans = make(chan int)
func main() {
go func() {
// range会直到channel被close才会停止,停止前会阻塞后面的语句
for v := range chans {
fmt.Println(v)
}
// <-chans
// channel中无值,会阻塞下边语句执行。range时,会阻塞到channel关闭,再接着执行下边的语句
fmt.Println("读取channel")
}()
fmt.Println("main start...")
time.Sleep(time.Second * 2)
chans <- 2
// close(chans)
time.Sleep(time.Second * 3)
fmt.Println("main end...")
}
result:使用range取channel值,若未close,会一直等待channel的值,并阻塞后面语句执行。
3)
package main
import (
"fmt"
"time"
)
var chans = make(chan int)
func main() {
go func() {
// range会直到channel被close才会停止,停止前会阻塞后面的语句
for v := range chans {
fmt.Println(v)
}
// <-chans
// channel中无值,会阻塞下边语句执行。range时,会阻塞到channel关闭,再接着执行下边的语句
fmt.Println("读取channel")
}()
fmt.Println("main start...")
time.Sleep(time.Second * 2)
chans <- 2
close(chans)
time.Sleep(time.Second * 3)
fmt.Println("main end...")
}
result:加上close()。当channel被关闭后,range跳出,执行协程剩余语句。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)