文章

流程控制

流程控制

if

if语句

如果条件为真,则进入下一句;如果条件为假,则跳过下面的语句

  • 如果逻辑表达式成立,就会执行{}里的内容。
  • 逻辑表达式不需要加()。
  • "{"必须紧跟在逻辑表达式后面,不能另起一行。
package main

import "fmt"

func main() {
   var a int = 4
   if a > 5 {
      fmt.Println("我比它大")
   }
   if a < 5 {
      fmt.Println("我比它小")
   }
}

image-20221216075357836

package main

import "fmt"

func main() {
   if c, d, e := 5, 9, 2; c < d && (c > e || c > 3) { //初始化多个局部变量。复杂的逻辑表达式
      fmt.Println("fit")
   }
}
  • 逻辑表达中可以含有变量或常量。
  • if句子中允许包含1个(仅1个)分号,在分号前初始化一些局部变量(即只在if块内可见)。

If-else的用法

package main

import (
   "fmt"
   "strings"
)

func main() {
   color := "black"
   if color == "red" { //if只能有一个
      fmt.Println("stop")
   } else if color == "green" {
      fmt.Println("go")
   } else if color == "yellow" { //else if可以有0个、一个或者连续多个
      fmt.Println("stop")
   } else { //else有0个或1个
      fmt.Printf("invalid traffic signal: %s\n", strings.ToUpper(color))
   }
}

if嵌套语句

字面意思,就是if里面还有if

package main

import "fmt"

func main() {
   var a int = 100
   var b int = 200
   if a == 100 {
      fmt.Println("a满足条件")
      if b == 200 {
         fmt.Println("b满足条件")
      }
   }

}

image-20221216075715840

package main

import "fmt"

func main() {
   //验证密码
   var a, b int
   var pwd int = 20221216
   fmt.Print("请输入密码:")
   fmt.Scan(&a)

   //验证密码是否正确
   if a == pwd {
      fmt.Printf("请再次输入密码:")
      fmt.Scan(&b)
      if b == pwd {
         fmt.Println("登录成功")
      } else {
         fmt.Println("登录失败,第二次密码错误")
      }
   } else {
      fmt.Println("登录失败,密码错误")

   }
}

image-20221216080425252

switch

switch语句用于基于不同条件执行不同动作,每一个case分支都是唯一的,从上至下逐一匹配,知道匹配为止

switch var1{
case var1:
  ...
case var2:
  ...
  default:
  ...
}
package main

import "fmt"

func main() {
   var sore int = 90
   switch sore {
   case 90:
      fmt.Println("A")
   case 80:
      fmt.Println("B")
   case 70:
      fmt.Println("c")
   default:
      fmt.Println("D")
   }
   //switch默认的条件 bool = true
   switch {
   case false:
      fmt.Println("false")
   case true:
      fmt.Println("true")
   default:
      fmt.Println("other")

   }

}

image-20221216081357318

  • switch-case-default可能模拟if-else if-else,但只能实现相等判断。
  • switch和case后面可以跟常量、变量或函数表达式,只要它们表示的数据类型相同就行。
  • case后面可以跟多个值,只要有一个值满足就行。
package main

import "fmt"

func add(a int) int {
   return a + 10
}
func switch_expression() {
   var a int = 5
   switch add(a) { //switch后跟一个函数表达式
   case 15: //case后跟一个常量
      fmt.Println("right")
   default:
      fmt.Println("wrong")
   }

   const B = 15
   switch B { //switch后跟一个常量
   case add(a): //case后跟一个函数表达式
      fmt.Println("right")
   default:
      fmt.Println("wrong")
   }
}
func main() {
   switch_expression()
}

image-20230313210546570

  switch后带表达式时,switch-case只能模拟相等的情况;如果switch后不带表达式,case后就可以跟任意的条件表达式。

package main

import "fmt"

func main() {
   switch_condition()
}
func switch_condition() {
   color := "yellow"
   switch color {
   case "green":
      fmt.Println("go")
   case "red", "yellow": //用逗号分隔多个condition,它们之间是“或”的关系,只需要有一个condition满足就行
      fmt.Println("stop")
   }

   //switch后带表达式时,switch-case只能模拟相等的情况;如果switch后不带表达式,case后就可以跟任意的条件表达式
   switch {
   case add(5) > 10:
      fmt.Println("right")
   default:
      fmt.Println("wrong")
   }
}
func add(a int) int {
   return a + 10
}

image-20230313210723457

switch Type

package main

import "fmt"

func switch_type() {
   var num interface{} = 6.5
   switch num.(type) { //获取interface的具体类型。.(type)只能用在switch后面
   case int:
      fmt.Println("int")
   case float32:
      fmt.Println("float32")
   case float64:
      fmt.Println("float64")
   case byte:
      fmt.Println("byte")
   default:
      fmt.Println("neither")
   }

   switch value := num.(type) { //相当于在每个case内部申明了一个变量value
   case int: //value已被转换为int类型
      fmt.Printf("number is int %d\n", value)
   case float64: //value已被转换为float64类型
      fmt.Printf("number is float64 %f\n", value)
   case byte, string: //如果case后有多个类型,则value还是interface{}类型
      fmt.Printf("number is inerface %v\n", value)
   default:
      fmt.Println("neither")
   }

   //等价形式
   switch num.(type) {
   case int:
      value := num.(int)
      fmt.Printf("number is int %d\n", value)
   case float64:
      value := num.(float64)
      fmt.Printf("number is float64 %f\n", value)
   case byte:
      value := num.(byte)
      fmt.Printf("number is byte %d\n", value)
   default:
      fmt.Println("neither")
   }
}
func main() {
   switch_type()
}

image-20230313211024181

fallthrough

当命中某一个case时,强行进入下一个case。

fallthrough穿透:如果使用了fallthrough穿透case,就会强制执行后面一条的case语句,fallthrough不会判断下一条case的表达式结果是否为true

package main

import "fmt"

func main() {
   a := false
   switch a {
   case false:
      fmt.Println("1.case条件为false")
      fallthrough //case 穿透的,不管下一个条件满不满足,都会执行
   case true:
      if a == false {
         break //终止case 穿透
      }
      fmt.Println("2.case条件为true")

   }
}

image-20221216082740002

去掉if a == false { break //终止case 穿透 }

结果为image-20221216082837135

for

for循环是一个循环控制结构,可以执行指定次数的循环

for 条件的起始值;循环条件;控制变量自增或者自减

for 初始化局部变量;条件表达式;后续操作

  • 局部变量指仅在for块内可见。
  • 初始化变量可以放在for上面。
  • 后续操作可以放在for块内部。
  • 只有条件判断时,前后的分号可以不要。
  • for{}是一个无限循环。
package main

import "fmt"

func main() {
   for i := 0; i <= 10; i++ {
      fmt.Print(i, " ")
   }
   fmt.Println("\n================")
   k := 0
   for ; k < 20; k++ {
      fmt.Print(k, " ")
   }
   fmt.Println("\n================")

   m := 0
   for m < 20 {
      fmt.Print(m, " ")
      m++
   }
   fmt.Println("\n================")
   //计算1到10的数字之和
   var num int = 0
   for j := 1; j <= 10; j++ {
      num += j
   }
   fmt.Println(num)
}

image-20221216131335136

for range

  • 遍历数组或切片
    • for i, ele := range arr
  • 遍历string
    • for i, ele := range “我会唱ABC” //ele是rune类型
  • 遍历map,go不保证遍历的顺序
    • for key, value := range m
  • 遍历channel,遍历前一定要先close
    • for ele := range ch
    • for range拿到的是数据的拷贝

break与continue

  • break与continue用于控制for循环的代码流程,并且只针对最靠近自己的外层for循环。
  • break:退出for循环,且本轮break下面的代码不再执行。
  • continue:本轮continue下面的代码不再执行,进入for循环的下一轮。

break结束当前整个循环

package main

import "fmt"

func main() {
   for i := 0; i < 11; i++ {
      if i == 6 {
         break
      }
      fmt.Println(i)
   }

}

image-20221216131539999

continue结束当次循环

package main

import "fmt"

func main() {
   for i := 0; i < 11; i++ {
      if i == 6 {
         break
      }
      fmt.Print(i, " ")
   }
   fmt.Println("\n-----------------")
   for j := 0; j < 11; j++ {
      if j == 6 {
         continue
      }
      fmt.Print(j, " ")
   }

}

image-20221216131742443

goto与Label

package main

import (
   "fmt"
   "time"
)

func main() {
   var i int = 4
   count := 0
MY_LABEL:
   i += 3
   count++
   fmt.Println(i)
   fmt.Println("我执行了", count, "次")
   time.Sleep(2 * time.Second)
   goto MY_LABEL//返回定义MY_LABEL的那一行,把代码再执行一遍(会进入一个无限循环)
}

image-20230313212131246

package main

import "fmt"

func main() {
   i := 10
   if i%2 == 0 {
      goto L1 //Label指示的是某一行代码,并没有圈定一个代码块,所以goto L1也会执行L2后的代码
   } else {
      goto L2 //先使用Label
   }
L1:
   i += 3
   fmt.Println(i)
L2: //后定义Label。Label定义后必须在代码的某个地方被使用
   i *= 3
   fmt.Println(i)
}

image-20230313212619268

goto与Label结合可以实现break的功能,甚至比break更强大。

for i := 0; i < SIZE; i++ {
L2:
for j := 0; j < SIZE; j++ {
	goto L1
}
}
L1:
xxx
  • break、continue与Label结合使用可以跳转到更外层的for循环。
  • continue和break针对的Label必须写在for前面,而goto可以针对任意位置的Label。
package main

import "fmt"

func break_label() {
   const SIZE = 5
   arr := [SIZE][SIZE]int{}
L1:
   for i := 0; i < SIZE; i++ {
   L2:
      fmt.Printf("第一层for循环---开始检查第%d行\n", i)

      if i%2 == 1 {
      L3:
         for j := 0; j < SIZE; j++ {
            fmt.Printf("第二层for循环---开始检查第%d列\n", j)
            if arr[i][j]%3 == 0 {
               break L1 //直接退出最外层的fot循环
            } else if arr[i][j]%3 == 1 {
               goto L2 //continue和break针对的Label必须写在for前面,而goto可以针对任意位置的Label
            } else {
               break L3
            }
         }
      }
   }
}
func main() {
   break_label()
}

image-20230313213307767

License:  CC BY 4.0 test