开发者学堂课程【Go 语言核心编程 - 面向对象、文件、单元测试、反射、TCP 编程:管道的注意事项和细节(2)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/626/detail/9763
管道的注意事项和细节(2)
一、 使用 select 可以解决从管道取数据的阻塞问题【案例演示】
建 demo02,新建一个文件 main.go
Package main
Import (
“fmt”
“time”
)
Func main() {
//使用select可以解决从管道取数据的阻塞问题
//1,定义一个管道 10个数据int
讲解:假设有10个数字,5个字符串
Intchan := make (chan int,10)
For i: = 0;I < 10 ; i++{
Intchan <- i
}
//2,定义一个管道 5个数据 string
Stringchan := make(chan string,5)
For i := 0; i< 5; i++{
Stringchan <- “hello” + fmt . sprintf(“%d”, i)
}
讲解:放入一个字符串
//传统的方法在遍历管道时,如果不关闭会阻塞而导致 deadlock
讲解:关闭管道确实可以解决问题,但是有的时候我们在写代码的时候知道什么时候关闭是一件很难的问题,在遇到很难的代码时,关闭是一件很困难的事情,因此要学会使用新的方法。
//问题。在实际开发中,可能我们不好确定什么时候关闭该管道,
//可以使用 select 方式解决
讲解:先用一个始循环,select 的基本语法如下
select{
casev :=<-管道:语句
default:语句
Label :
For{
Select{
//注意:这里,如果 intchan 一直没有关闭,不会一直阻塞而 deadlock
//会自动到下一个 case 匹配
case v:= < - intchan:
讲解:使用这个方法 < - intchan: 没有关闭也不会阻塞,如果取不到数据,他会自动往下走,
fmt.printf(“从intchan读取的数据%d\n”, v)
time. Sleep(time.second)
case v := <- stringchan :
讲解:如果都取不到,就停止了。
fmt.printf(“从stringchan读取的数据%s\n”, v)
time. Sleep(time.second)
default :
fmt.printf(“都取不到了,不玩了,程序员可以加入自己的逻辑\n”, v)
//return
break
讲解:在写好代码之后,可以运行一遍,看出来的效果,
我们可以看到,他都取完了。如果只在下面加一个 break,是没有用的,跳不出去。所以要在前面加一个 label,下面可以用 break,也可以用 return,这个就很厉害,。我们先来试试break有没有用,为了页面排列整齐,我们每个都给他加一个休眠,time. Sleep(time.second),同时加一个 time 包,最后运行代码,
我们可以看到他在取完数据之后也没有退出,这个时候我们有两个解决方法。一种方法是这一段是一个协程,最后放一个 return,就可以。这个 return 代表这一个协程都返回到 main,不执行了,这个时候我们运行代码
我们可以看到它就在取不到的时候就退出循环,是正常的。但是如果想加入自己的逻辑也是可以的。第二种方法就是加入一个 label 和 break,但是 label 尽量不要使用,因为用的很少,但是他也能达到效果。运行代码:
可以看到运行是正常的。
讲解:break 和 return 是有区别的。如果写了 return,下面的代码是没有机会运行的,也不能写;如果使用 break,那下面的代码是可以使用的。