008 GO-基本流程控制(if for switch select)
包括:条件分支、循环和并发。
一、if语句
if 100> number{ number += 3 } |
if num := 4; 100 > num {
}
// num:=4 被称为——if语句的初始化子句
if语句内部对number的访问和赋值都只会涉及到第二次声明的那个number变量。这种现象也被叫做标识符的遮蔽。上述代码被执行完毕之后,第二次声明的number变量的值会是7,而第一次声明的number变量的值仍会是0。
1.2、if else 语句
if 100 > number { number += 3 } else { number -= 2 } |
1.3、else if
if 100 > number { number += 3 } else if 100 < number { number -= 2 } else { fmt.Println("OK!") } |
注意:对 if代码块内部 的变量进行操作,不会影响 外部的同名变量值——标识符的重声明
if number := 4; 100 > number { number += 3 } else if 100 < number { number -= 2 } else { fmt.Println("OK!") }
二、switch 语句
2.1 表达式 switch 语句
2.1.1 switch 判断值
var name string
name = "Golang"
switch name {
case "Golang":
fmt.Println("A programming language from google")
case "Rust":
fmt.Println("A programming language from mozilla")
default:
fmt.Println("Unknown! please search google!")
}
|
注意:defautl case 不一定在最后,可以是第一个case,或者出现在任意顺位上。
2.1.2 包含初始化子句的switch
2.2 类型 switch语句
- 1、紧跟 case 关键字的不是表达式,而是【类型说明符】。 由若干个类型字面量组成,且多个类型字面量之间由英文逗号分隔。
- 表达式很特殊(起到了类型断言的作用)。如: v.(type) v 必须代表一个接口类型的值。——此表达式,只能在 switch 语句中 充当 switch 表达式 使用。
示例:
2.3 关键字 fallthrough
- 作用是:使控制权流转到 下一个 case
- fallthrough 仅能作为 case 语句中的最后一条语句出现。
- 并且——包含其的 case 语句 不能是其 所属 switch 语句的 最后一条 case 语句
三、for 语句
3.1 普通for(包含for子句)
for语句代表着循环。一条语句通常由关键字for、初始化子句、条件表达式、后置子句和以花括号包裹的代码块组成。其中,初始化子句、条件表达式和后置子句之间需用分号分隔。示例如下:
for i := 0; i < 10; i++ { fmt.Print(i, " ") }
我们可以省略掉初始化子句、条件表达式、后置子句中的任何一个或多个,不过起到分隔作用的分号一般需要被保留下来,除非在仅有条件表达式或三者全被省略时分号才可以被一同省略
3.2 for (range子句)
range子句替换掉 for 子句。 range子句包含一个或两个迭代变量(绑定迭代出的值)
for i, v := range "Go语言" { fmt.Printf("%d: %c\n", i, v) } |
- 字符串迭代出 字符索引、值
- 数组值、数组的指针值 、切片 ——索引,以及被迭代的某一个元素
- 字典: 第一个是字典的键,第二个是字典的值
- 通道:
携带range子句的for语句还可以应用于一个通道值之上。其作用是不断地从该通道值中接收数据,不过每次只会接收一个值。注意,如果通道值中没有数据,那么for语句的执行会处于阻塞状态。无论怎样,这样的循环会一直进行下去。直至该通道值被关闭,for语句的执行才会结束。
3.3 break 和 continue
break 使得 其所属的 for 循环立即结束。
continue 之后的语句和会被忽略,进入下一次迭代。——跳过当前的循环,进入下一次迭代
3.4 示例:循环遍历字典
func main() { map1 := map[int]string{1: "Golang", 2: "Java", 3: "Python", 4: "C"} for i,v:=range map1{ //fmt.Println(v) fmt.Printf("%d: %v\n",i,v) } } |
四、select 语句
select语句属于条件分支流程控制方法,不过它只能用于通道。
,select语句中的case关键字只能后跟用于通道的发送操作的表达式以及接收操作的表达式或语句。
4.1 示例--接收通道数据
取出通道的值,做case 判断
ch1 := make(chan int, 1) ch2 := make(chan int, 1) // 省略若干条语句 select { case e1 := <-ch1: fmt.Printf("1th case is selected. e1=%v.\n", e1) case e2 := <-ch2: fmt.Printf("2th case is selected. e2=%v.\n", e2) default: fmt.Println("No data!") } |
如果该select语句被执行时通道ch1和ch2中都没有任何数据,那么肯定只有default case会被执行。但是,只要有一个通道在当时有数据就不会轮到default case执行了。显然,对于包含通道接收操作的case来讲,其执行条件就是通道中存在数据(或者说通道未空)。如果在当时有数据的通道多于一个,那么Go语言会通过一种伪随机的算法来决定哪一个case将被执行。
4.2 发送通道数据
另一方面,对于包含通道发送操作的case来讲,其执行条件就是通道中至少还能缓冲一个数据(或者说通道未满)。类似的,当有多个case中的通道未满时,它们会被随机选择。请看下面的示例: ch3 := make(chan int, 100) // 省略若干条语句 select { case ch3 <- 1: fmt.Printf("Sent %d\n", 1) case ch3 <- 2: fmt.Printf("Sent %d\n", 2) default: fmt.Println("Full channel!") } |
case执行条件的满足与否取决于其操作的通道在当时的状态。这里特别强调一点,即:未被初始化的通道会使操作它的case永远满足不了执行条件。对于针对它的发送操作和接收操作来说都是如此。
4.3 break 语句 用于select
break语句也可以被包含在select语句中的case语句中。它的作用是立即结束当前的select语句的执行,不论其所属的case语句中是否还有未被执行的语句
通道关闭之后 ——断言才为 false
package main
import "fmt"
func main() { ch4 := make(chan int, 1) for i := 0; i < 4; i++ { select { case e, ok := <-ch4: //fmt.Println(ok) if !ok { fmt.Println(ok) fmt.Println("End.") return } fmt.Println(e) close(ch4) default: fmt.Println("No Data!") ch4 <- 1 } } } |