Golang流程控制

Golang当中的流程控制

  1. if if语句由一个布尔表达式后紧跟一个或多个语句组成

Go变成语言种if语句语法如下

  1. 1.可省略条件表达式括号
  2. 2.持初始化语句,可定义代码块局部变量
  3. 3.代码块左 括号必须在条件表达式尾部
  4. if 布尔条件表达式{
  5. //代码块
  6. }
  1. switch switch语句用于基于不同条件执行不同动作,每一个case分支都是唯一的,从上直下逐一测试,直到匹配为止,Golang switch 分支表达式可以是任意类型不限于常量。可省略break 默认自动终止
  1. switch var1 {
  2. case val1:
  3. ...
  4. case val2:
  5. ...
  6. default:
  7. ...
  8. }
  1. select语句 select语句类似于switch语句,但是select会随机执行一个可运行的case,如果没有case可运行,它将阻塞,直到由case可运行。select是Go的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接受。select随机执行一个可运行的case。如果没有case可运行。它将阻塞,一个默认的子句应该是可运行的。
  1. select {
  2. case communication clause :
  3. statement(s);
  4. case communication clause :
  5. statement(s);
  6. /* 你可以定义任意数量的 case */
  7. default : /* 可选 */
  8. statement(s);
  9. }
  • 每个case都必须是一个通信
  • 所有cahnnel表达式都会被求值
  • 所有被发送的表达式都会被求值
  • 如果任意某个通信可以进行,它就执行;其他被忽略
  • 如果有多个case都可以运行,select会随机公平的选出一个执行。其他不会
  • 如果有default子句,则执行该语句
  • 如果没有defaultt子句,select将阻塞,直到某个通信可以运行;Go不会重新对channle进行求值
  1. 循环语句for for循环时一个循环控制结构,可以执行指定次数的循环。

```go for init;condition;post{} for condition{} for{} //init 初始化条件 //condition 条件表达式 //post赋值表达式 1.对表达式进行赋值

  1. 判断赋值表达式是否满足condition条件 若其值为真,满足循环条件,进入循环体

func main() { for i := 0; i < 3; i++ { fmt.Println(“第一种循环”) } var k = 0 for k<3 { fmt.Println(“第二种循环”) k++ } for { fmt.Println(“第三种循环”) break } }

  1. > 5.
  2. 循环语句range
  3. > Golangrange类似迭代器操作,返回(索引,值)或(键,值)
  4. > ```go
  5. for key,value:=rage map{
  6. newMap[key]=value
  7. }
  8. //for循环的range可以对 slice、map、数组、字符串等进行迭代
  9. //举例
  10. type student struct {
  11. Name string
  12. Age int
  13. }
  14. func pase_student() {
  15. m := make(map[string]*student)
  16. stus := []student{
  17. {Name: "zhou", Age: 24},
  18. {Name: "li", Age: 23},
  19. {Name: "wang", Age: 22},
  20. }
  21. for _, stu := range stus {
  22. m[stu.Name] = &stu
  23. }
  24. }
  25. //map[li:0xc000098420 wang:0xc000098420 zhou:0xc000098420]
  26. //对于以上代码进行对map赋值最后发现vlaue的值结果都是一样的,原因如下:
  27. //使用 for range 语法的控制结构最终应该也会被golang的编译器转换成普通的 for 循环,所以for range实际上会被先转换成经典的for循环再真正执行,而正是这个转换过程常常会留坑。
  28. //&v实际上是对循环内部同一个短变量的取址,因此res中存的其实都是同一个地址,这个地址中的值实际上是最后一次循环赋的值。
  29. //因为for range在遍历值类型时,其中的stu变量是一个值的拷贝,当使用&获取指针时,实际上是获取到v这个临时变量的指针,而v变量在for range中只会创建一次,之后循环中会被一直重复使用,所以在m赋值的时候其实都是stu变量的指针,而&stu最终会指向student最后一个元素的值拷贝
1Value 2Value
string index str[index]
array/slice index array[index]
map key m[]
channel element

for 和channel的使用场景比较:

for range
遍历array和slice 遍历array和slice
遍历key为整形递增的map 遍历key为整形递增的map
遍历string 遍历string
遍历channel
遍历key为string类型的map,同时获取key和value

for range可以完成for可以做的事情,还可以完成for不能做的

  1. Goto label Goto时调整执行位置,与continue、break配合标签label的结果并不相同。Goto没有限制
  1. func main() {
  2. var i = 10
  3. if i > 1 {
  4. //跳转到AA标签进行执行
  5. goto AA
  6. }
  7. //AA标签 标签名区分大小写、AA和aa是2个标签
  8. AA:
  9. for i := 0; i < 11; i++ {
  10. fmt.Println(i)
  11. }
  12. }
  1. break label break label的跳转标签必须放在for循环前面,并且在break label跳出循环不再执行for循环里面的代码
  1. Stop:
  2. for i := 0; i < 3; i++ {
  3. fmt.Println("打印====>" + strconv.Itoa(i))
  4. if i == 1 {
  5. break Stop
  6. }
  7. fmt.Println("skip====>" + strconv.Itoa(i))
  8. //打印====>0
  9. //skip====>0
  10. //打印====>1
  11. }
  1. continue label continue label的作用跟break label都只能用于修饰循环。continue label跳出本次循环 还会继续下次循环
  1. fmt.Println("=====================")
  2. ContinueLabel:
  3. for i := 0; i < 3; i++ {
  4. fmt.Println("打印====>" + strconv.Itoa(i))
  5. if i == 1 {
  6. continue ContinueLabel
  7. }
  8. fmt.Println("skip====>" + strconv.Itoa(i))
  9. //打印====>0
  10. //skip====>0
  11. //打印====>1
  12. //打印====>2
  13. //skip====>2
  14. }