6.1 if语句

go语言的常用控制流程有if和for,没有while, 而switch和goto是为了简化代码,降低重复代码,属于扩展的流程控制。

if语句的结构:

  1. if 布尔表达式 {
  2. /* 在布尔表达式为 true 时执行 */
  3. }
  4. if 布尔表达式 {
  5. /* 在布尔表达式为 true 时执行 */
  6. } else {
  7. /* 在布尔表达式为 false 时执行 */
  8. }
  9. if 布尔表达式1 {
  10. /* 在布尔表达式1为 true 时执行 */
  11. } else if 布尔表达式2{
  12. /* 在布尔表达式1为 false ,布尔表达式2为true时执行 */
  13. } else{
  14. /* 在上面两个布尔表达式都为false时,执行*/
  15. }
  1. package main
  2. import "fmt"
  3. func main() {
  4. /* 定义局部变量 */
  5. var a int = 10
  6. /* 使用 if 语句判断布尔表达式 */
  7. if a < 20 {
  8. /* 如果条件为 true 则执行以下语句 */
  9. fmt.Printf("a 小于 20\n" )
  10. }
  11. fmt.Printf("a 的值为 : %d\n", a)
  12. }

if还有一个变体也很常用

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. if num := 10; num % 2 == 0 { //checks if number is even
  7. fmt.Println(num,"is even")
  8. } else {
  9. fmt.Println(num,"is odd")
  10. }
  11. }
  1. if err := Connect(); err != nil {
  2. }

这种写法可 以将返回值与判断放在一行进行处理,而且返回值的作用范围被限制在if、 else 语句组合中。
提示:
在编程中,变量在其实现了变量的功能后 ,作用范围越小 ,所造成的问题可能性越小,每一个变量代表一个状态,有状态的地方,状态就会被修改,函数的局部变量只会影响一个函数的执行, 但全局 变量可能会影响所有代码的执行状态,因此限制变量的作用范围对代码的稳定性有很大的帮助 。

  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. func test() error {
  7. return errors.New("error")
  8. }
  9. func main() {
  10. if err := test(); err != nil {
  11. fmt.Println("error happen")
  12. }
  13. fmt.Println(err) //此处会报错
  14. }

6.2 for循环

  1. Go 语言的 For 循环有 3 种形式,只有其中的一种使用分号。
    1. //和 C 语言的 for 一样:
    2. for init; condition; post { }
    3. //和 C 的 while 一样:
    4. for condition { }
    5. //和 C 的 for(;;) 一样:
    6. for { }
  • init: 一般为赋值表达式,给控制变量赋初值;
  • condition: 关系表达式或逻辑表达式,循环控制条件;
  • post: 一般为赋值表达式,给控制变量增量或减量。

for语句执行过程如下:

  • 1、先对表达式 1 赋初值;
  • 2、判别赋值表达式 init 是否满足给定条件,若其值为真,满足循环条件,则执行循环体内语句,然后执行 post,进入第二次循环,再判别 condition;否则判断 condition 的值为假,不满足条件,就终止for循环,执行循环体外语句。

6. 条件/循环语句 - 图1

  1. for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:
    1. for key, value := range oldMap {
    2. newMap[key] = value
    3. }
    ```go package main import “fmt”

func main() { strings := []string{“bobby”, “imooc”} for i, s := range strings { fmt.Println(i, s) }

  1. numbers := [6]int{1, 2, 3, 5}
  2. for i,x:= range numbers {
  3. fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
  4. }

}

  1. <a name="AHxEm"></a>
  2. # 6.3 goto语句
  3. Go语言的goto语句可以无条件转移到过程中指定的行。<br />goto语句通常与条件语句配合使用,可用来实现条件转移,构成循环,跳出循环体等功能。<br />但是,在结构化程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,使理解和调试程序都产生困难。<br />goto语法格式如下:
  4. ```powershell
  5. goto label;
  6. ...
  7. label:statement;

6. 条件/循环语句 - 图2

  1. package main
  2. import "fmt"
  3. func main() {
  4. /* 定义局部遍历 */
  5. var a int = 10
  6. /* 循环 */
  7. LOOP:
  8. for a < 20 {
  9. if a == 15 {
  10. /* 跳过迭代 */
  11. a = a + 1
  12. goto LOOP
  13. }
  14. fmt.Printf("a的值为:%d\n", a)
  15. a++
  16. }
  17. }

应用场景

使用goto退出多层循环

  1. package main
  2. import "fmt"
  3. func main() {
  4. var breakAgain bool
  5. //外循环
  6. for x := 0; x < 10; x++ {
  7. //内循环
  8. for y := 0; y < 10; y++ {
  9. //满足某个条件时 退出循环
  10. if y == 2 {
  11. //设置退出标记
  12. breakAgain = true
  13. //退出本次循环
  14. break
  15. }
  16. }
  17. // 根据标记 还需要退出一次循环
  18. if breakAgain {
  19. break
  20. }
  21. }
  22. fmt.Println("done")
  23. }
  1. //优化后
  2. package main
  3. import "fmt"
  4. func main() {
  5. for x := 0; x < 10; x++ {
  6. for y := 0; y < 10; y++ {
  7. if y == 2 {
  8. //跳转到标签
  9. goto breakHere
  10. }
  11. }
  12. }
  13. //手动返回, 避免执行进入标签
  14. return
  15. //标签
  16. breakHere:
  17. fmt.Println("done")
  18. }

使用goto集中处理错误

多处错误处理存在代码重复时是非常棘手的,例如:

  1. err := firstCheckError()
  2. if err != nil {
  3. fmt.Println(err)
  4. exitProcess()
  5. return
  6. }
  7. err = secondCheckError()
  8. if err != nil {
  9. fmt.Println(err)
  10. exitProcess()
  11. return
  12. }
  13. fmt.Println("done")

上述代码修改一下

  1. err := firstCheckError()
  2. if err != nil {
  3. goto onExit
  4. }
  5. err = secondCheckError()
  6. if err != nil {
  7. goto onExit
  8. }
  9. fmt.Println("done")
  10. return
  11. onExit:
  12. fmt.Println(err)
  13. exitProcess()

6.4 switch语句

  1. switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。
    1. switch var1 {
    2. case val1:
    3. ...
    4. case val2:
    5. ...
    6. default:
    7. ...
    ```go package main

import “fmt”

func main() { / 定义局部变量 / var grade string = “B” var marks int = 90

switch marks { case 90: grade = “A” case 80: grade = “B” case 50,60,70 : grade = “C” default: grade = “D”
}

switch { case grade == “A” : fmt.Printf(“优秀!\n” )
case grade == “B”, grade == “C” : fmt.Printf(“良好\n” )
case grade == “D” : fmt.Printf(“及格\n” )
case grade == “F”: fmt.Printf(“不及格\n” ) default: fmt.Printf(“差\n” ); } fmt.Printf(“你的等级是 %s\n”, grade );
}

  1. <a name="de7sV"></a>
  2. ## Type Switch
  3. switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。<br />Type Switch 语法格式如下:
  4. ```go
  5. switch x.(type){
  6. case type:
  7. statement(s);
  8. case type:
  9. statement(s);
  10. /* 你可以定义任意个数的case */
  11. default: /* 可选 */
  12. statement(s);
  13. }
  1. package main
  2. import "fmt"
  3. func main() {
  4. var x interface{}
  5. switch i := x.(type) {
  6. case nil:
  7. fmt.Printf(" x 的类型 :%T",i)
  8. case int:
  9. fmt.Printf("x 是 int 型")
  10. case float64:
  11. fmt.Printf("x 是 float64 型")
  12. case func(int) float64:
  13. fmt.Printf("x 是 func(int) 型")
  14. case bool, string:
  15. fmt.Printf("x 是 bool 或 string 型" )
  16. default:
  17. fmt.Printf("未知型")
  18. }
  19. }

一分支多值

不同的 case 表达式使用逗号分隔。

  1. var a = "mum"
  2. switch a {
  3. case "mum", "daddy":
  4. fmt.Println("family")
  5. }

分支表达式

  1. var r int = 11
  2. switch {
  3. case r > 10 && r < 20:
  4. fmt.Println(r)
  5. }

6.5 python中为什么没有switch

查看Python官方:PEP 3103-A Switch/Case Statement

发现其实实现Switch Case需要被判断的变量是可哈希的和可比较的,这与Python倡导的灵活性有冲突。在实现上,优化不好做,可能到最后最差的情况汇编出来跟If Else组是一样的。所以Python没有支持。

  1. https://www.python.org/dev/peps/pep-3103/
  2. score = 90
  3. switch = {
  4. 90: lambda : print("A"),
  5. 80: lambda : print("B"),
  6. 70: lambda : print("C"),
  7. }
  8. switch[score]()
  1. class switch(object):
  2. def __init__(self, value):
  3. self.value = value
  4. self.fall = False
  5. def __iter__(self):
  6. """Return the match method once, then stop"""
  7. yield self.match
  8. raise StopIteration
  9. def match(self, *args):
  10. """Indicate whether or not to enter a case suite"""
  11. if self.fall or not args:
  12. return True
  13. elif self.value in args: # changed for v1.5, see below
  14. self.fall = True
  15. return True
  16. else:
  17. return False
  18. # The following example is pretty much the exact use-case of a dictionary,
  19. # but is included for its simplicity. Note that you can include statements
  20. # in each suite.
  21. v = 'ten'
  22. for case in switch(v):
  23. if case('one'):
  24. print 1
  25. break
  26. if case('two'):
  27. print 2
  28. break
  29. if case('ten'):
  30. print 10
  31. break
  32. if case('eleven'):
  33. print 11
  34. break
  35. if case(): # default, could also just omit condition or 'if True'
  36. print "something else!"
  37. # No need to break here, it'll stop anyway
  38. # break is used here to look as much like the real thing as possible, but
  39. # elif is generally just as good and more concise.
  40. # Empty suites are considered syntax errors, so intentional fall-throughs
  41. # should contain 'pass'
  42. c = 'z'
  43. for case in switch(c):
  44. if case('a'): pass # only necessary if the rest of the suite is empty
  45. if case('b'): pass
  46. # ...
  47. if case('y'): pass
  48. if case('z'):
  49. print "c is lowercase!"
  50. break
  51. if case('A'): pass
  52. # ...
  53. if case('Z'):
  54. print "c is uppercase!"
  55. break
  56. if case(): # default
  57. print "I dunno what c was!"
  58. # As suggested by Pierre Quentel, you can even expand upon the
  59. # functionality of the classic 'case' statement by matching multiple
  60. # cases in a single shot. This greatly benefits operations such as the
  61. # uppercase/lowercase example above:
  62. import string
  63. c = 'A'
  64. for case in switch(c):
  65. if case(*string.lowercase): # note the * for unpacking as arguments
  66. print "c is lowercase!"
  67. break
  68. if case(*string.uppercase):
  69. print "c is uppercase!"
  70. break
  71. if case('!', '?', '.'): # normal argument passing style also applies
  72. print "c is a sentence terminator!"
  73. break
  74. if case(): # default
  75. print "I dunno what c was!"
  76. # Since Pierre's suggestion is backward-compatible with the original recipe,
  77. # I have made the necessary modification to allow for the above usage.