Go语言--第4章 流程控制

第4章 流程控制 

主要内容

 

4.1 条件判断--if

Go语言规定与if匹配的左括号“{” 必须与if 和表达式放在同一行,如果尝试将“{”放在其他位置,将会触发编译错误

与else 匹配的 “{” 也必须与else 在同一行

else也必须与上-个if 或else if 的右边的大括号在一行

格式:

if 表达式1 {
    分支1
} else if 表达式2 {
    分支2
} else {
    分支3
}
// > 10

特殊写法

if 还有特殊的写法,可以在if表达式之前添加一个执行语句,再根据变量值进行判断,如:

  if err := Connect(); err != nil {
    fmt.Println(err)
    return
  }

Connect() 为假设的函数,err := Connect() 可以视为一个表达式

4.2 构建循环--for

Go语言中所有循环类型均可以使用for关键字完成

for 初始语句;条件表达式; 结束语句 {
循环体代码
}

for 循环可以通过break,goto,return,panic语句强制退出循环

4.2.1 for中初始语句--开始执行的语句

初始语句可以被忽略,但是初始语句之后的分号必须要写

 step := 2
  for ; step > 0; step-- {
    fmt.Println(step)
  }
  // 2
  // 1

  

4.2.2 for中条件表达式--控制是否循环的开关

条件表达式也可以被忽略,忽略默认为无限循环

  1. 结束循环时带可执行语句的无限循环

  var i int
  for ; ; i++ {
    if i > 10 {
      fmt.Println("i > 10")
      break;
    }
  }
  // i > 10

  

  1. 无限循环

 for {
    if i > 10 {
      fmt.Println("i > 10")
      break
    }
    i++
  }
    // i > 10

  

4.2.3 for中结束语句--每次循环结束时执行的语句

在结束每次循环前执行的语句,被break 、goto、return、panic等语句强制推出

示例:

​
  // 遍历九九乘法表
  for x:=1; x < 10; x++ {
    for y :=1; y <= x; y++ {
      sum := x * y
      fmt.Printf("%d * %d = %d ", x, y, sum )
    } 
    fmt.Printf("\r\n")
  }
​
结果

1 * 1 = 1

2 * 1 = 2 2 * 2 = 4

3 * 1 = 3 3 * 2 = 6 3 * 3 = 9

4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 4 * 4 = 16

5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25

6 * 1 = 6 6 * 2 = 12 6 * 3 = 18 6 * 4 = 24 6 * 5 = 30 6 * 6 = 36

7 * 1 = 7 7 * 2 = 14 7 * 3 = 21 7 * 4 = 28 7 * 5 = 35 7 * 6 = 42 7 * 7 = 49

8 * 1 = 8 8 * 2 = 16 8 * 3 = 24 8 * 4 = 32 8 * 5 = 40 8 * 6 = 48 8 * 7 = 56 8 * 8 = 64

9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81

  

4.4 键值循环(for range)-- 直接获得对象的索引和数据

Go语言可以使用for range遍历、数据、切片、字符串、map及通道(channel)

规律:

  • 数组、切片、字符串返回索引值

  • map返回键和值

  • 通道(channel)只返回通道内的值

4.4.1 遍历数组、切片--获得索引和元素

for key, value := range []int{1,2,3,4} {
    fmt.Printf("key: %d, value: %d\r\n", key, value )
}
​
//key: 0, value: 1
//key: 1, value: 2
//key: 2, value: 3
//key: 3, value: 4
​

4.4.2 遍历字符串--获得字符

for key, value := range "abcdef" {
    fmt.Printf("key: %d, value: 0x%x\r\n", key, value )
}
​
//key: 0, value: 0x61
//key: 1, value: 0x62
//key: 2, value: 0x63
//key: 3, value: 0x64
//key: 4, value: 0x65
//key: 5, value: 0x66

 

4.4.3 遍历字典map--获得键和值

m := map[int]string{
    1 : "one",
    2 : "two",
    3 : "three",
  }   
for key,value := range m {
    fmt.Printf("key: %d, value: %s\r\n", key, value )
}
// key: 1, value: one
// key: 2, value: two
// key: 3, value: three

  

4.4.3 遍历通道channel -- 接受通道数据


 c := make(chan int)
  // 启动一个goroutine,往通道中推送数据1、2、3,然后关闭通道
  go func() {
    c <- 1
    c <- 2
    c <- 3
    close(c)
  }()
​
  for v := range c {
    fmt.Println(v)
  }
  
  // 1
  // 2
  // 3

  

4.4.5 遍历中只选择需要的变量

不需要获得的key或value,可以用下划线“-”代替,即匿名变量

匿名变量,可理解为占位符,本身不会进行空间分配,不会占用变量的名字


for _, value := range []int{1,2,3,4} {
    fmt.Printf("value: %d\r\n",  value )
}
​
// value: 1
// value: 2
// value: 3
// value: 4

 

4.4.6 for总结

for 功能:

  1. Go语言for包含初始条件,条件表达式、结束语句,这3个均可省略

  2. for range 支持数组、切片、字符串、map、通道遍历

  3. 可使用匿名变量获取只需要的变量

4.5 分支选择(switch) -- 拥有多个条件分支的判断

4.5.1 基本写法

switch中每个case与case间是独立的代码块,不需要通过break语句跳出当前case代码块以避免执行到下一行

Go语言规定每一个switch只能有一个default分支

  var a = "hello"
  switch a {
  case "hello":
    fmt.Println(1)
  case "world":
    fmt.Println(2)
  default:
    fmt.Println(0)
  }

  

分支常见情况:

  1. 一分支多值

​
switch a {
case "hello", "world" :
fmt.Println("Hi")
}
​ 
  1. 分支表达式

​
var r int = 11
var s int = 5
switch {
    case r > 10 && r <20:
    fmt.Println(r)
    case s > 2 && s <10:
    fmt.Println(s)
}
// 11

  

如果只有一个变量判断的时候,switch后面可以不用添加变量r

4.5.2 跨越case的fallthrough -- 兼容c语言的case设计

fallthrough关键字用来实现case分支间的执行,应为go语言的case的是独立的代码块

  str := "hello"
  switch {
  case str == "hello":
    fmt.Println("hello")
    fallthrough
  case str != "world":
    fmt.Println("world")
  }
  // hello
  // world

  

4.6 跳转到指定代码标签(goto)

goto语句通过标签进行代码间的无条件跳转,可以快速跳出循环避免重复退出上有一定帮助

4.6.1 使用goto退出多层循环

原代码:

packeage main
import ("fmt")
func main() {
    var breakAgain bool
    for  x := 0; x < 10; x++ {
        for y := 0; y <10; y++ {
            if y == 2 {
                breakAgain = true
               break
            }
        }
        if breakAgain {
          break
        }
  }
  fmt.Println("done") 
}

 

使用goto语句进行优化:

使用goto语句后,无须额外的变量就可以进行快速退出所有的循环

packeage main
import ("fmt")
func main() {
  for  x := 0; x < 10; x++ {
    for y := 0; y <10; y++ {
      if y == 2 {
        // 跳转到标签
        goto breakHere
      }
    }
​
  }
  // 手动返回,避免执行进入标签
  return
​
  // 标签
  breakHere:
    fmt.Println("done")
}

  

4.6.2 统一错误处理

err := firstCheckError()
if err != nil {
  goto onExit
}
​
err = secondCheckError()
if err != nil {
  goto onExit
}
​
fmt.Println("done")
return
​
onExit:
  fmt.Println(err)

  

4.7 跳出指定循环(break)

break语句可以跳出for 、switch 和select代码块

break语句后面添加标签,表示退出某个标签对应的代码块,标签必须定义在对应的for、switch和select的代码块上

packeage main
import ("fmt")
func main() {
​
  loop:
    for i:=1; i<=3; i++ {
      for j := 0; j<5;j++ {
        switch j {
        case 2:
          fmt.Println(i,j)
                    // 退出 loop标签下的这个双循坏代码
          break loop 
        case 3:
          fmt.Println(i,j)
          break loop
        }
      }
    }
}
 

  

4.8 跳出当前循坏(continue)

continue语句结束当前循坏,开始下一个循环,仅限于for循环内使用

continue语句后面添加标签时,表示开始标签对应的循环

packeage main
import ("fmt")
func main() {
​
  loop:
    for i:=0; i<=3; i++ {
      for j := 0; j<5;j++ {
        switch j {
        case 2:
          fmt.Println(i,j)
          continue loop
        } 
      }
    }
  
    // 0 2
    // 1 2
    // 2 2
    // 3 2
}
    

  

 

 
posted @ 2019-11-16 01:02  洪先森  阅读(212)  评论(0编辑  收藏  举报