1 如何检测chain关掉
1.1. 使用断言
func main() {
var ch chan int
ch = make(chan int, 10)
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
for {
var b int
// 如果Ok==false,说明chan 已经关掉了
// 如果这里直接写成b=ch,那么会无限循环,不断输出0
b,ok := <-ch
if ok == false {
fmt.Println("chan is close")
break
}
fmt.Println(b)
}
}
1.2. 使用range
func main() {
var ch chan int
ch = make(chan int, 1000)
for i := 0; i < 1000; i++ {
ch <- i
}
close(ch)
for v := range ch {
fmt.Println(v)
}
}
1.3 close
如上面的例子,如果不close(ch),会报deadlock错误,
原因分析
为什么会死锁?非缓冲信道上如果发生了流入无流出,或者流出无流入,也就导致了死锁。或者这样理解 Go启动的所有goroutine里的非缓冲信道一定要一个线里存数据,一个线里取数据,要成对才行
range不等到信道关闭是不会结束读取的。也就是如果 缓冲信道干涸了,那么range就会阻塞当前goroutine, 所以死锁咯。
2.异常捕获
如果go中出现了panic,整个进程会退出,可以加异常捕获
func test() {
defer func() {
if err := recover(); err != nil {
fmt.Println("panic:", err)
}
}()
var m map[string]int
m["stu"] = 100
}
func calc() {
for {
fmt.Println("i'm calc")
time.Sleep(time.Second)
}
}
func main() {
num := runtime.NumCPU()
runtime.GOMAXPROCS(num - 1)
go test()
for i := 0; i < 2; i++ {
go calc()
}
time.Sleep(time.Second * 10000)
}