赞
踩
- if 布尔表达式1 {
- 分支1
- } else if 布尔表达式2 {
- 分支2
- } else{
- 分支3
- }
当布尔表达式1的结果为true时,执行分支1,否则判断布尔表达式2,如果满足则执行分支2,都不满足时,则执行分支3。 if判断中的else if和else都是可选的,可以根据实际需要进行选择。
在 if 表达式之前添加一个执行语句
- if n := "abc"; x > 0 { // 初始化语句未必就是定义变量, 如 println("init") 也是可以的。
- println(n[2])
- } else if x < 0 { // 注意 else if 和 else 左大括号位置。
- println(n[1])
- } else {
- println(n[0])
- }
switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上直下逐一测试,直到匹配为止。 Golang switch 分支表达式可以是任意类型,不限于常量。可省略 break,默认自动终止,但是可以使用fallthrough强制执行后面的case代码。
- switch var1 {
- case val1:
- ...
- case val2:
- ...
- fallthrough
- default:
- ...
- }
- package main
-
- import "fmt"
-
- func main() {
- /* 定义局部变量 */
- var grade string = "B"
- var marks int = 90
-
- switch marks {
- case 90: grade = "A"
- 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 )
- }

以上代码执行结果为:
- 优秀!
- 你的等级是 A
switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。
- switch x.(type){
- case type:
- statement(s)
- case type:
- statement(s)
- /* 你可以定义任意个数的case */
- default: /* 可选 */
- statement(s)
- }
例如:
- package main
-
- import "fmt"
-
- func main() {
- var x interface{}
- //写法一:
- switch i := x.(type) { // 带初始化语句
- case nil:
- fmt.Printf(" x 的类型 :%T\r\n", i)
- case int:
- fmt.Printf("x 是 int 型")
- case float64:
- fmt.Printf("x 是 float64 型")
- case func(int) float64:
- fmt.Printf("x 是 func(int) 型")
- case bool, string:
- fmt.Printf("x 是 bool 或 string 型")
- default:
- fmt.Printf("未知型")
- }
- }

以上代码执行结果为:
x 的类型 :<nil>
select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该总是可运行的。
- 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, i2 int
- select {
- // = <-c1 表示等待并接收c1通道的数据
- 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")
- }
- }

以上代码执行结果为:
no communication
select可以监听channel的数据流动
select的用法与switch语法非常类似,由select开始的一个新的选择块,每个选择条件由case语句来描述
与switch语句可以选择任何使用相等比较的条件相比,select由比较多的限制,其中最大的一条限制就是每个case语句里必须是一个IO操作
- select { //不停的在这里检测
- case <-chanl : //检测有没有数据可以读
- //如果chanl成功读取到数据,则进行该case处理语句
- case chan2 <- 1 : //检测有没有可以写
- //如果成功向chan2写入数据,则进行该case处理语句
-
-
- //假如没有default,那么在以上两个条件都不成立的情况下,就会在此阻塞//一般default会不写在里面,select中的default子句总是可运行的,因为会很消耗CPU资源
- default:
- //如果以上都没有符合条件,那么则进行default处理流程
- }
在一个select语句中,Go会按顺序从头到尾评估每一个发送和接收的语句。
如果其中的任意一个语句可以继续执行(即没有被阻塞),那么就从那些可以执行的语句中任意选择一条来使用。 如果没有任意一条语句可以执行(即所有的通道都被阻塞),那么有两种可能的情况:
①如果给出了default语句,那么就会执行default的流程,同时程序的执行会从select语句后的语句中恢复。
②如果没有default语句,那么select语句将被阻塞,直到至少有一个case可以进行下去。
1.超时判断
- //比如在下面的场景中,使用全局resChan来接受response,如果时间超过3S,resChan中还没有数据返回,则第二条case将执行
- 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) {
- //...
- }
2.退出
- //主线程(协程)中如下:
- var shouldQuit=make(chan struct{})
- fun main(){
- {
- //loop
- }
- //...out of the loop
- select {
- case <-c.shouldQuit:
- cleanUp()
- return
- default:
- }
- //...
- }
-
- //再另外一个协程中,如果运行遇到非法操作或不可处理的错误,就向shouldQuit发送数据通知程序停止运行
- close(shouldQuit)

3.判断channel是否阻塞
- //在某些情况下是存在不希望channel缓存满了的需求的,可以用如下方法判断
- ch := make (chan int, 5)
- //...
- data:=0
- select {
- case ch <- data:
- default:
- //做相应操作,比如丢弃data。视需求而定
- }
Golang for支持三种循环方式,包括类似 while 的语法。
for循环是一个循环控制结构,可以执行指定次数的循环。
普通for循环:
for init; condition; post { }
替代while的for循环:
for condition { }
替代 while (true)的for循环:
for { }
例如:
- s := "abc"
-
- for i, n := 0, len(s); i < n; i++ { // 常见的 for 循环,支持初始化语句。
- println(s[i])
- }
-
- n := len(s)
- for n > 0 { // 替代 while (n > 0) {}
- println(s[n]) // 替代 for (; n > 0;) {}
- n--
- }
-
- for { // 替代 while (true) {}
- println(s) // 替代 for (;;) {}
- }
- for i,x:= range numbers { //range使用方法
- fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
- }

上面for循环优化:
- func main() {
- s := "abcd"
-
- for i, n := 0, len(s); i < n; i++ { // 避免多次调用 len 函数。
- println(i, s[i])
- }
- }
Golang range类似迭代器操作,返回 (索引, 值) 或 (键, 值)。
for 循环的 range 格式可以对 slice、map、数组、字符串及通道(channel)等进行迭代循环。格式如下:
- for key, value := range oldMap {
- newMap[key] = value
- }
通过for range遍历的返回值有以下规律:
"_" 这个特殊变量。| 1st value | 2nd value | ||
|---|---|---|---|
| string | index | s[index] | unicode, rune |
| array/slice | index | s[index] | |
| map | key | m[key] | |
| channel | element |
使用:
- func main() {
- s := "abc"
- // 忽略 2nd value,支持 string/array/slice/map。
- for i := range s {
- println(s[i])
- }
- // 忽略 index。
- for _, c := range s {
- println(c)
- }
- // 忽略全部返回值,仅迭代。
- for range s {
-
- }
-
- m := map[string]int{"a": 1, "b": 2}
- // 返回 (key, value)。
- for k, v := range m {
- println(k, v)
- }
- }

goto语句通过标签进行代码间的无条件跳转。goto语句可以在快速跳出循环、避免重复退出上有一定的帮助。
例如双层嵌套的for循环要退出时:
- func gotoDemo2() {
- for i := 0; i < 10; i++ {
- for j := 0; j < 10; j++ {
- if j == 2 {
- // 设置退出标签
- goto breakTag
- }
- fmt.Printf("%v-%v\n", i, j)
- }
- }
- return
- // 标签
- breakTag:
- fmt.Println("结束for循环")
- }
break语句可以结束for、switch和select的代码块。单个跳出循环直接break,多层跳出指定一下就行了。
- func breakDemo1() {
- BREAKDEMO1:
- for i := 0; i < 10; i++ {
- for j := 0; j < 10; j++ {
- if j == 2 {
- break BREAKDEMO1
- }
- fmt.Printf("%v-%v\n", i, j)
- }
- }
- fmt.Println("...")
- }
continue语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for循环内使用。
- func continueDemo() {
- forloop1:
- for i := 0; i < 5; i++ {
- // forloop2:
- for j := 0; j < 5; j++ {
- if i == 2 && j == 2 {
- continue forloop1
- }
- fmt.Printf("%v-%v\n", i, j)
- }
- }
- }
参考文件:
条件语句if :https://www.fansimao.com/991496.html
switch case: https://www.fansimao.com/991511.html
go条件语句select : https://www.fansimao.com/991523.html
go 循环语句for : https://www.fansimao.com/991534.html
go 循环语句range: https://www.fansimao.com/991545.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。