我们经常需要代码在满足一定条件时进行执行,或者需要重复执行代码多次,此时需要选择条件语句(if-else if- else)或选择语句(switch case)及循环语句(for)

一、 条件语句

段子:老婆给当程序员的老公打电话:下班顺路买十个包子,如果看到卖西瓜的,买一个。
当晚老公手捧一个包子进了家门…老婆怒道:你怎么只买一个包子?!老公甚恐,喃喃道:
因为我真看到卖西瓜的了。
老婆:买十个包子,如果有卖西瓜的,买一个西瓜
老公:如果有卖西瓜的,买一个包子,否则买十个包子

1) if

image.png
当 if 表达式的结果为 true 则执行语句块内代码

2) if-else

image.png
当 if 表达式结果为 true,则执行 if 语句块内代码,否则执行 else 语句块内代码

3) else if

成绩评优: [90, 100]=>优秀(A), [80, 90) => 良好(B), [60, 80) => 及格(C), [0, 60) =>
不及格(D)
使用 if-else 语句实现
image.png
使用 if-else if-else 语句实现
image.png

  1. func main() {
  2. var socre int
  3. fmt.Println("请输入您的分数:")
  4. fmt.Scan(&socre)
  5. if socre >= 90 {
  6. fmt.Println("成绩优秀")
  7. } else if socre >= 80 {
  8. fmt.Println("成绩良好")
  9. } else if socre >= 60 {
  10. fmt.Println("成绩及格")
  11. } else {
  12. fmt.Println("请退学吧")
  13. }
  14. }

当 if 表达式结果为 true,则执行 if 语句块内代码,否则依次从上到下判断 else if 表达式结果,若结果为 true 则执行对应语句块内代码并退出 if-else if-else 语句,若 if 和else if 表达式均为 false,则执行 else 语句块内代码

4) 初始化子语句

可以在 if 语句中初始化语句块内的局部变量,多个语句之间使用逗号(;)分隔
image.png

5) 总结

对于条件语句必须有 if 语句,可以有 0 个或多个 else if 语句,最多有 1 个 else 语句,语句从上到下执行,执行第一个条件表达式为 true 的语句块并退出,否则执行 else 语句块退出

二、 选择语句

根据输入条件的不同选择不同的语句块进行执行(多分支)

1) switch-case 单值

image.png
image.png

func main() {
    var operation string
    fmt.Printf("是否选择安装:Y/N\n")
    fmt.Scan(&operation)
    switch operation {
    case "Y", "y":
        fmt.Println("确认安装")
    case "N", "n":
        fmt.Println("取消安装")
    }
}
  • swtich 语句后面跟接变量,此时选择与变量相同的 case 语句块执行并退出,若所有 case均不相同则执行 default 语句块,case 语句中可包含多个不同的值进行匹配

    2) switch-case 表达式

    image.png

  • switch 后不跟接变量,此时自上到下选择第一个表达式为 true 的 case 语句块执行并退出,若所有 case 表达式均为 false,则执行 default 语句块

    func main() {
      socre := 0
      fmt.Println("请输入您的成绩:")
      fmt.Scan(&socre)
      switch {
      case socre >= 90:
          fmt.Println("优秀")
      case socre >= 80:
          fmt.Println("良好")
      case socre >= 60:
          fmt.Println("及格")
      default:
          fmt.Println("退学吧")
      }
    }
    

    3) 初始化子语句

  • 可以在 switch 语句中初始化语句块内的局部变量,多个语句之间使用逗号(;)分隔,注意初始化表达式时后面的逗号(;)不能省略

image.png

4) fallthrough

switch-case 默认执行 case 语句后退出,若需要继续执行下一个 case 语句块,可以在 case语句块中使用 fullthrough 进行声明
image.png

func main() {
    switch score := 80; {
    case score >= 90:
        fmt.Println("优秀")
    case score >= 80:
        fmt.Println("良好")
        fallthrough
    case score >= 60:
        fmt.Println("及格")
    default:
        fmt.Println("不及格")
    }
}

[root@i-vzozw11z test]# go run main.go 
良好
及格

5) 总结

对于选择语句可以有 0 个或多个 case 语句,最多有 1 个 default 语句,选择条件为 true的 case 语句块开始执行并退出,若所有条件为 false,则执行 default 语句块并退出。可以通过 fallthrough 修改执行退出行为,继续执行下一条的 case 或 default 语句块

三、循环语句

问题:计算 1-100 所有整数的和

1) for

image.png
for 语句后有三个子语句分别为:初始化子语句,条件子语句和后置子语句
执行顺序为:
a) 初始化子语句
b) 条件子语句
c) 语句块
d) 后置子语句
e) b->c->d
f) …
g) 直到条件子语句为 false 结束循环

2) break 与 continue 语句

image.png
break 用于跳出循环,当条件满足则结束循环
continue 用于跳过循环,当条件满足这跳过本次循环进行后置或条件子语句执行

3) 类 while

for 子语句可以只保留条件子语句,此时类似于其他语言中的 while 循环
image.png

4) 无限循环

for 子语句全部省略,则为无限循环(死循环),s 常与 break 结合使用
image.png
可使用 ctrl+z 中止程序运行
image.png

5) for-range

用于遍历可迭代对象中的每个元素,例如字符串,数组,切片,映射,通道等
image.png
针对包含 Unicode 字符的字符串遍历是需要使用 for-range,range 返回两个元素分别为字节索引和 rune 字符,可通过空白标识符忽略需要接收的变量

四、label 与 goto

可以通过 goto 语句任意跳转到当前函数指定的 label 位置
image.png
break 和 continue 后也可以指定 label 用于指定跳出或跳过指定 label 同层级的循环
image.png

五、 练习

1) 乘法口诀

func main() {
    for i := 1; i <= 9; i++ {
        for j := 1; j <= i; j++ {
            fmt.Printf("%d * %d = %d\t", j, i, i*j)
        }
        fmt.Println()
    }
}

2) 猜数游戏

func main() {
    // 设置随机数种子
    rand.Seed(time.Now().Unix())
    const maxGuessNum = 5
    var isOk bool
    var guess int
    var input int

    for {
        //生成随机数0 - 100
        // guess := rand.Int() % 100
        guess = rand.Intn(100)
        for i := 0; i < maxGuessNum; i++ {
            fmt.Print("请输入你猜的值:")
            fmt.Scan(&input)
            if guess == input {
                fmt.Printf("太聪明了, 你猜测%d次就猜对了\n", i+1)
                isOk = true
                break
            } else if input > guess {
                fmt.Printf("太大了, 你还有%d猜测机会\n", maxGuessNum-i-1)
            } else {
                fmt.Printf("太小了, 你还有%d猜测机会\n", maxGuessNum-i-1)
            }
        }
        if !isOk {
            fmt.Println("太笨了, 游戏结束")
        }
        var text string
        fmt.Print("重新开始游戏吗?(y/n)")
        fmt.Scan(&text)
        if text != "y" {
            break
        }
    }
}