1.if-else结构

  1. if condition1 {
  2. // do something
  3. } else if condition2 {
  4. // do something else
  5. }else {
  6. // catch-all or default
  7. }

1)判断一个字符串是否为空:

  • if str == “” { … }
  • if len(str) == 0 {…}

2)判断运行 Go 程序的操作系统类型,这可以通过常量 runtime.GOOS 来判断。

  1. if runtime.GOOS == "windows" {
  2. . ..
  3. } else { // Unix-like
  4. . ..
  5. }

3)if 可以包含一个初始化语句

  1. if initialization; condition {
  2. // do something
  3. }

2.测试多返回值函数的错误

Go 语言的函数经常使用两个返回值来表示执行是否成功:返回某个值以及 true 表示成功;返回零值(或 nil)和 false 表示失败

  1. an, err := strconv.Atoi(orig)
  2. if err != nil {
  3. fmt.Printf("orig %s is not an integer - exiting with error\n", orig)
  4. return
  5. }

这是测试 err 变量是否包含一个真正的错误(if err != nil)的习惯用法。如果确实存在错误,则会打印相应的错误信息然后通过 return 提前结束函数的执行。我们还可以使用携带返回值的 return 形式,例如 return err

  1. value, err := pack1.Function1(param1)
  2. if err != nil {
  3. fmt.Printf("An error occured in pack1.Function1 with parameter %v", param1)
  4. return err
  5. }
  6. // 未发生错误,继续执行:

在main函数我们想要在错误发生的同时终止程序的运行,我们可以使用 os 包的 Exit 函数

  1. if err != nil {
  2. fmt.Printf("Program stopping with error %v", err)
  3. os.Exit(1)
  4. }

可以将错误的获取放置在 if 语句的初始化部分

  1. if err := file.Chmod(0664); err != nil {
  2. fmt.Println(err)
  3. return err
  4. }

或者将 ok-pattern 的获取放置在 if 语句的初始化部分,然后进行判断

  1. if value, ok := readData(); ok {
  2. }

3.switch结构

  1. switch var1 {
  2. case val1:
  3. ...
  4. case val2:
  5. ...
  6. default:
  7. ...
  8. }

1)变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式
2)可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3。
3)变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式
4)如果在执行完每个分支的代码后,还希望继续执行后续分支的代码,可以使用 fallthrough 关键字来达到目的

  1. switch i {
  2. case 0: // 空分支,只有当 i == 0 时才会进入分支
  3. case 1:
  4. f() // 当 i == 0 时函数不会被调用
  5. }
  1. switch i {
  2. case 0: fallthrough
  3. case 1:
  4. f() // 当 i == 0 时函数也会被调用
  5. }

5)switch 语句的第二种形式是不提供任何被判断的值(实际上默认为判断是否为 true),然后在每个 case 分支中进行测试不同的条件。当任一分支的测试结果为 true 时,该分支的代码会被执行。

  1. switch {
  2. case condition1:
  3. ...
  4. case condition2:
  5. ...
  6. default:
  7. ...
  8. }
  1. package main
  2. import "fmt"
  3. func main() {
  4. var num1 int = 7
  5. switch {
  6. case num1 < 0:
  7. fmt.Println("Number is negative")
  8. case num1 > 0 && num1 < 10:
  9. fmt.Println("Number is between 0 and 10")
  10. default:
  11. fmt.Println("Number is 10 or greater")
  12. }
  13. }

6)switch 语句的第三种形式是包含一个初始化语句

  1. switch initialization {
  2. case val1:
  3. ...
  4. case val2:
  5. ...
  6. default:
  7. ...
  8. }
  1. switch a, b := x[i], y[j]; {
  2. case a < b: t = -1
  3. case a == b: t = 0
  4. case a > b: t = 1
  5. }

4.for结构

1)形式1:
for 初始化语句; 条件语句; 修饰语句 {}
2)形式2:
for 条件语句 {}
3)形式3:(无限循环)
for { }
4)形式4:(for-range结构)
for ix, val := range coll { }

练习:写一个从 1 打印到 100 的程序,但是每当遇到 3 的倍数时,不打印相应的数字,但打印一次 “Fizz”。遇到 5 的倍数时,打印 Buzz 而不是相应的数字。对于同时为 3 和 5 的倍数的数,打印 FizzBuzz(提示:使用 switch 语句)。

  1. package main
  2. import "fmt"
  3. func main() {
  4. for i := 1; i <= 100; i++ {
  5. switch a, b := i % 3, i % 5; {
  6. case a == 0 :
  7. fmt.Print("Fizz")
  8. if b == 0 {
  9. fmt.Print("Buzz")
  10. }
  11. case b == 0 : fmt.Print("Buzz");
  12. default : fmt.Print(i)
  13. }
  14. fmt.Println()
  15. }
  16. }

5. Break 与 continue

一个 break 的作用范围为该语句出现后的最内部的结构,它可以被用于任何形式的 for 循环(计数器、条件判断等)。但在 switch 或 select 语句中(详见第 13 章),break 语句的作用结果是跳过整个代码块,执行后续的代码。
关键字 continue 忽略剩余的循环体而直接进入下一次循环的过程,但不是无条件执行下一次循环,执行之前依旧需要满足循环的判断条件。

6.标签与 goto

使用标签和 goto 语句是不被鼓励的(有需要时再来了解)