浅析Go语言中Channel的各种用法
目录
- Go语言基础四
- if定义
- 单层if语法格式
- 语法警告
- 多层if语法格式
- Switch定义
- Type Switch
- Select定义
- Select语句注意事项
- Select用法补充
- 退出
- 判断Channel状态
Go语言基础四
今天我们要来学习if语句,也就是大家口中的判断语句,我们首先来看一下if语句的定义
if定义
条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句。相信读者看到这儿,也是云里雾里的感觉,我们怎么来表示true和false呢?
单层if语法格式
- 可省略条件表达式括号。
- 持初始化语句,可定义代码块局部变量。
- 代码块左 括号必须在条件表达式尾部。
if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */ }
这里要为读者介绍的是,如果if后面的条件语句程序给出的数能够满足,则我们表示为true
;如果不能,则返回false
package main import "fmt" func main() { a := 3 if a > 2 { fmt.Println(ByQYKV"true") } else { fmt.Println("false") } }
如代码块所示,这里我们定义了一个变量a的值为3,接下来是一个if判断,如果该数值>2,则调用函数打印输出true
;否则返回false
。换句话说,我们这里即是对a变量的一个判断,至于调用函数打印输出的内容,由读者自行决定
语法警告
在Go语法中,不支持三元操作符(三目运算符) a > b ? a : b,如果读者对三元运算符较感兴趣,可以移步至Java了解三元运算符(其本质上也是一种if判断形式)
package main import "fmt" func main() { /* 定义局部变量 */ var a int = 10 /* 使用 if 语句判断布尔表达式 */ if a < 20 { /* 如果条件为 true 则执行以下语句 */ fmt.Printf("a 小于 20\n" ) } fmt.Printf("a 的值为 : %d\n", a) }
上方是关于if判断的一个小练习,读者自行体会即可;if
在布尔表达式为 true
时,其后紧跟的语句块执行,如果为 false
则执行 else
语句块。
package main import "fmt" func main() { /* 局部变量定义 */ var a int = 100 /* 判断布尔表达式 */ if a < 20 { /* 如果条件为 true 则执行以下语句 */ fmt.Printf("a 小于 20\n" ) } else { /* 如果条件为 false 则执行以下语句 */ fmt.Printf("a 不小于 20\n" ) } fmt.Printf("a 的值为 : %d\n", a) }
在Go语言
中,if语句也支持嵌套处理,即可以实现多重if判断以达到程序想要的结果
多层if语法格式
if 布尔表达式 1 {
/* 在布尔表达式 1 为 true 时执行 */ if 布尔表达式 2 { /* 在布尔表达式 2 为 true 时执行 */ }}
package main import "fmt" func main() { /* 定义局部变量 */ var a int = 100 var b int = 200 /* 判断条件 */ if a == 100 { /* if 条件语句为 true 执行 */ if b == 200 { /* if 条件语句为 true 执行 */ fmt.Printf("a 的值为 100 , b 的值为 200\n" ) } } fmt.Printf("a 值为 : %d\n", a ) fmt.Printf("b 值为 : %d\n", b ) }
如上图所示,我们在if
语句里面嵌套了另一个if语句,即是在默认a == 100的情况下写出对变量b的值的判断,最终调用函数打印输出a和b的值
有时候我们多个变量匹配同一个值,就会用到Switch
语句
Switch定义
switch
语句用于基于不同条件执行不同动作,每一个 case
分支都是唯一的,从上直下逐一测试,直到匹配为止。golang switch
分支表达式可以是任意类型,不限于常量。可省略 break
,默认自动终止。
Switch语法格式
switch var1 { case val1: ... case val2: ... default: ... }
package main import "fmt" func main() { /* 定义局部变量 */ var grade string = "B" var marks int = 90 switch marks { case 90: grade = "Ahttp://www.devze.com" case 80: grade = "B" case 50,60,70 : grade = "C" default: grade = "D" } switch { case grade == "A" : fmt.Printf("优秀!\n" ) case grade == "B", grade == "C" : fmt.Printf("良好\n" ) case grade == "D" : fmt.Printf("及格\n" ) case grade == "F": fmt.Printf("不及格\n" ) default: fmt.Printf("差\n" ) } fmt.Printf("你的等级是 %s\n", grade ) }
由上方代码块可知,我们定义了两个局部变量grade和marks,对marks进行Switch
判断操作,当case
满足不同的值的时候,调用函数打印输出的值也不一样
Type Switch
switch
语句还可以被用于 type-switch
来判断某个 interface 变量中实际存储的变量类型
Type Switch语法格式
switch x.(type){ case type: statement(s) case type: statement(s) /* 你可以定义任意个数的case */ default: /* 可选 */ statement(s) }
由于Type Switch
用途不是特别的多,作者在这里不作详细描述,读者可以去官网自行查询相关文档进行学习
Select定义
select
语句类似于switch
语句,但是select
会随机执行一个可运行的case
。如果没有case
可运行,它将阻塞,直到有case
可运行。select
是Go
中的一个控制结构,类似于用于通信的switch
语句。每个case
必须是一个通信操作,要么是发送要么是接收。select
随机执行一个可运行的case
。如果没有case
可运行,它将阻塞,直到有case
可运行。一个默认的子句应该总是可运行的。
Select语法格式
select { case communication clause : statement(s); case communication clause : statement(s); /* 你可以定义任意数量的 case */ default : /* 可选 */ statement(s); }
Select语句注意事项
- 每个
case
都必须是一个通信 - 所有
channel
表达式都会被求值 - 所有被发送的表达式都会被求值
- 如果任意某个通信可以进行,它就执行;其他被忽略。
- 如果有多个
case
都可以运行编程,Select会随机公平地选出一个执行。其他不会执行。 - 如果有
default
子句,则执行该语句。 - 如果没有
default
字句,select
将阻塞,直到某个通信可以运行;Go
不会重新对channel
值重新进行求值。
package main import "fmt" func main() { var c1, c2, c3 chan int //通道机制 var i1, iByQYKV2 int select { case i1 = <-c1: fmt.Printf("received ", i1, " from c1\n") case c2 <- i2: fmt.Printf("sent ", i2, " to c2\n") case i3, ok := (<-c3): // same as: i3, ok := <-c3 if ok { fmt.Printf("received ", i3, " from c3\n") } else { fmt.Printf("c3 is closed\n") } default: fmt.Printf("no communication\n") } }
根据上方代码所示,定义了c1、c2、c3
三个变量,并且使用chan
通道。关于写法的解释:一个可以发送 int
类型数据的 channel
一般写为 chan int
,根据上方的语法规则:如果有default
子句,则执行该语句,故上方代码块执行代码为:no communication
Select用法补充
- 我们可以使用
select
来监听channel
的数据流动 select
的用法与switch
语法非常类似,由select
开始的一个新的选择块,每个选择条件由case
语句来描述switch
语句可以选择任何使用相等比较的条件相比,select
由比较多的限制,其中最大的一条限制就是每个case
语句里必须是一个IO操作
- 如果每个
case
都未读取到,则Go语言
会自动读取default
语句所描述的东西,在正常情况下,每个select
程序都会有一个输出语句 - 如果既没有
case
语句满足,也不存在default
语句,则程序进入阻塞状态,系统会发出警告,直至疏通
超时判断
var resChan = make(chan int) // do request func test() { select { case data := <-resChan: doData(data) case <-time.After(time.Second * 3): fmt.Println("request time out") } } func doData(data int) { //... }
根据上方代码块可知,我们定义了一个select
语句,在第一条case
里面,我们将resChan
传给data
,如果在传输的过程中时长超过3s,则会执行第二条case
语句
退出
var shouldQuit=make(chan struct{}) fun main(){ { //loop 开发者_JAVA入门} //...out of the loop select { case <-c.shouldQuit: cleanUp() return default: } //... } //在另外一个协程中,如果运行遇到非法操作或不可处理的错误,就向http://www.devze.comshouldQuit发送数据通知程序停止运行 close(shouldQuit)
我们定义一个var类型的shouldQuit
变量用于结构体的通道,首先我们开启一个select循环,在case
里面调用通道方法,并且返回所对应的值;如果不满足,则返回default的值。同时我们在另外一个协程中,如果我们遇到了非法操作或不可处理的错误,就向shouldQuit
发送数据通知程序停止运行
判断Channel状态
ch := make (chan int, 5) //... data:=0 select { case ch <- data: default: }
有时候我们不喜欢缓存变慢,这样不利于我们去释放资源,因此我们可以用一个简单的判断方法去进行判断:首先我们开启一个int类型,长度为5的通道,在通道里面我们开启一个select
循环,如果data通道的值能被ch所接收,则执行该条语句,否则我们可对default语句
进行抛弃data等处理操作
到此这篇关于浅析Go语言中Channel的各种用法的文章就介绍到这了,更多相关Go语言Channel用法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
精彩评论