# Golang 流程控制

# 一、条件语句

# 1. if

  • 无需括号
  • if 条件上可以有初始化语句
if a < 20 {   
   //..
} else if a > 40 {
   //..
} else {
   //...
}

  • if 条件上可以有初始化语句,常用场景如下:
if err := callAMethod(); err != nil {
   // handle error
}

# 二、选择语句

# 1. switch

switch 有两种:

  • 表达式 switch:普通的 switch,用来代替多个 if else
  • 类型 switch:用来判断传入的数据类型

# 1.1 表达式 switch

package main

import "fmt"

func main() {
  grade := "B"
  marks := 90
  
  switch marks {
  case 90:
    grade = "A"
  case 80:
    grade = "B"
  case 70:
    grade = "C"
  case 60:
    grade = "D"
  default:
    grade ="E"
  }
  
  fmt.Printf("Your grade is %s\n", grade)
}

# 1.2 类型 switch

package main

var x interface{}

func main() {
  x = 1
  switch i:= x.(type) {   //取出 x 的类型,swicth 同样支持在表达式处进行初始化
  case nil:
    //...
  case int:
    //...
  case float64:
    //...
  case bool:
    //...
  case string:
    //...
  default:
    //...
  }
}

# 2. select

select 语句用于配合 channel 的读写操作,用于多个 channel 的并发读写操作。

switch 是从上往下按顺序执行,而 select 是随机选择一个 case 来判断,直到匹配其中的一个 case。

package main

import "fmt"

func main() {
	a := make(chan int, 1024) //初始一个 int channel
	b := make(chan int, 1024)

	for i := 0; i < 10; i++ {
		fmt.Printf("第 %d 次", i)
		a <- 1   //将一个值为 1 的 int 数据扔进 a
		b <- 1

		//select 语句
		select {
		case getA := <- a:   //从 a 中取数据
			fmt.Println("from a", getA)
		case getB := <- b:
			fmt.Println("from b", getB)
		}
	}
}

# 三、循环语句

# 1. for

for 语句后面跟 3 个子语句:

  1. 初始化子语句
  2. 条件子语句
  3. 后置子语句
for i := 1; i < 10; i++ {
  fmt.Println("", i)
}

# 2. range

每一个 for 语句都可以使用一个特殊的 range 语句,其作用类似于迭代器,用于轮询数组或者切片值中的每一个元素,也可以用于轮询字符串中的每一个字符,以及字典值中的每一个键值对,甚至还可以持续读取一个通道类型值中的元素。

右边表达式返回的类型 第一个值 第二个值
string index str[index],返回类型为 rune
array/slice index arr[index]
map key m[key]
channel element
m := make(map[string]string)
m["1"] = "1"
m["2"] = "2"
m["3"] = "3"

for k, v := range m {
  fmt.Printf("key is %s, value is %s", k, v)
}

# 四、延迟语句

# 1. defer

Go 语言中还有一个延迟语句 defer, defer 用于延迟调用指定函数,defer 关键字只能出现在函数内部。

func main() {
  defer fmt.Println("World")
  fmt.Println("Hello")
}

会返回:

Hello
World

defer 有 2 大特点:

  • defer 会在函数 return 之前,以及函数 panic 的时候执行

  • defer 的调用顺序有“栈”的感觉,先写的后调用

    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
    
    //最后是输出
    3
    2
    1
    

因为 defer 的特点,可以把 defer 语句用于回收资源、清理结尾等工作。

# 五、跳转语句

# 1. Label

Go 支持给 for、switch 或 select 等流程控制代码块打上标签,配合标签可以方便跳转到某一个地方继续执行带啊,有助于提高编程效率。

L1:
	handleError()

# 2. break

break 打断当前流程控制。

  • 打断 for 循环

    for i := 1; i <= 5 ; i++ {
      if  i >= 3 {
        	break //跳出 for 循环
      }
    }
    
  • 打断某个代码块

    LOOP1:
          for {
              x := 1
              switch {
              case x > 0:
                  fmt.Println("A")
                  break LOOP1 //跳到 LOOP1 代码块以外
              case x == 1:
                	fmt.Println("B")
              default:
                	fmt.Println("C")
              }
          }
    

# 3. continue

continue 用于跳转到指定代码块位置继续执行任务,continue 仅能用于 for 语句。

  • 进入下一轮 for 循环

    for i := 1; i <= 5 ; i++ {
      if  i >= 3 {
        	continue //立刻进入下一轮 for 循环
      }
    }
    
  • 回到某个位置继续执行

    LOOP1:
          for {
              x := 1
              switch {
              case x > 0:
                  fmt.Println("A")
                  continue LOOP1 //跳到 LOOP1 代码块继续执行
              case x == 1:
                	fmt.Println("B")
              default:
                	fmt.Println("C")
              }
          }
    

# 4. goto

goto 用于跳转到某个标签。

func main() {
  i := 1
  for {
    i ++
    if i > 10 {
      	goto END  //跳到 END 标签处执行
    }
    
  }
  
  END:
  		fmt.Println("end")
}
上次更新: 7/27/2021, 6:41:10 PM