管道细节注意
1.管道可以声明为只读或者只写:
var chan1 chan int //可读可写
var chan2 chan <- int//声明为只写
var chan3 <- chan int//声明为只读
(默认情况下为只读或者只写)
2.var chan2 chan <- int , chan2类型还是int,只是属性是只写。
用法
go send( ch, exitchan)
func send(ch chan <- int, exitchan chan struct{})
3.使用select 可以解决管道阻塞的问题
package main
import(
"fmt"
)
func main(){
intChan := make(chan int, 10)
for i:=0; i<10;i++{
intChan <- i
}
stringChan := make(chan string, 5)
for i:=0; i<5; i++{
stringChan <- "hello" + fmt.Sprintf("%d", i)
}
//传统方法在遍历管道时, 如果不关闭会导致阻塞,从而导致死锁
for {
select{
case v:=<-intChan: //这里intchan一直没有关闭,不会一直阻塞而死锁
//自动下一个case匹配
fmt.Printf("从intChan %v\n", v)
case v:= <-stringChan:
fmt.Printf("从stringChan读取的数据 %s\n", v)
default :
fmt.Printf("都娶不到了\n")
break
}
}
}
4.使用recover()函数解决不同协程间出现的panic,recover协程中的panic,不影响正常的协程工作
package main
import(
"fmt"
"time"
)
func hello(){
for i:=0 ; i<10; i++{
time.Sleep(time.Second)
fmt.Println("hello world")
}
}
func test(){
defer func(){
//知识点,recover()能捕获panic
/*在defer的函数中,执行recover调用会取回传至panic调用的错误值,恢复正常执行,停止恐慌过程。若recover在defer的函数之外被调用,它将不会停止恐慌过程序列。*/
if err := recover(); err!=nil{
fmt.Println("test() 发生错误", err)
}
}()
var Map map[int]string
Map[0] = "ggggg"
}
func main(){
go hello()
go test()
for i:=0; i < 10; i++{
fmt.Println("main() ok = ", i)
time.Sleep(time.Second)
}
}