GO 从 0 到 1 系列:5 go 语言流程控制语句

go 语言流程控制语句

程序流程控制介绍:

在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句。

1) 顺序控制

2) 分支控制(有判断条件)

3) 循环控制

在 GO 中流程控制语句有以下几个:

  • if 语句
  • switch语句
  • for循环
  • break与continue
  • goto语句与Label

1 if 语句

让程序有选择地执行,分支控制有以下三种:

  • 单分支
  • 双分支
  • 多分支

Go 的 if 还有一个强大的地方就是条件判断语句里面允许声明一个变量,这个变量的作用域只能在该条件逻辑块内,其他地方就起不了作用(举例说明)

1.1 单分支

基本语法:

if 条件表达式{   // 返回一个真或者假的 boll 值,真就执行代码块中的内容
    执行代码块
}

说明:当条件表达式为 True 时,就会执行得的代码

注意 {} 是必须有的,就算你只写一行代码这个大括号也要有

if 语句简单使用

if 5 > 9 {
    fmt.Println("5>9")
}
// 如果逻辑表达式成立,就会执行{}里的内容
// 逻辑表达式不需要加()
// "{"必须紧跟在逻辑表达式后面,不能另起一行

if 语句复杂使用

// 初始化多个局部变量 ; 号后面才是真正的逻辑判断语句
if c, d, e := 5, 9, 2; c < d && (c > e || c > 3) { 
    fmt.Println("fit")
}
// 逻辑表达中可以含有变量或常量

// if 句子中允许包含 1 个(仅1个)分号,在分号前初始化一些局部变量(即只在if块内可见)

所谓流程图:就是通过图形的方式来更加清晰的描述程序执行的这么一个过程。

1.2 if-else 双分支

color := "black"

// if只能有一个
if color == "red" { 
    fmt.Println("stop")
} else if color == "green" {
    fmt.Println("go")
} else if color == "yellow" { //else if 可以有 0 个、一个或者连续多个
    fmt.Println("stop")
} else {                      // else 有0个或1个
    fmt.Printf("invalid traffic signal: %s\n", strings.ToUpper(color))
}

1.3 if 表达式嵌套多分支

先看第一个表达式是否成立,如果成立执行代码块 1 就退出判断,如果为 false 不成立就看第二个表示是否成立,成立执行代码块 2 ,如果一直为 false 就一直执行,最后退出 if 判断。

也就是说只有条件表达式不成立的时候才回去执行后面的条件表达式

在 if 语句中还支持多个 if 语句的嵌套,太深的嵌套不利于代码的维护

如果在工作中最好不要嵌套 3 次

if xxx {
    if xxx {
    }else if xxx{
    }else{
    }
}else{
    if xxx {
    }else{
    }
}

if 表达式嵌套

如下代码中,演示休息日的睡觉和看电影,如果是周日周六的 22 点就表示为睡觉,如果不是就输出看电影

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    weekday := now.Weekday()
    hour := now.Hour()
    fmt.Println(weekday, hour)

    // 如果是周天周六,如果 hour 大于等于 22 就睡觉,否则看电影
    if weekday.String() != "Saturday" && weekday.String() != "Sunnday" {
        if hour >= 22 {
            fmt.Println("睡觉")
        } else if hour < 22 {
            fmt.Println("看电影")
        }
    }
}

输出

[11:42:02 root@go day2]#go run main.go 
Tuesday 11
看电影

1.3.1 规避多层嵌套

但是我们可以通过语言层面对这种层层嵌套的语句进行拆减

// 可以看到这代码一共嵌套了 3 层 if,对于后期极度不利于代码维护
package main

import "fmt"

func main() {
    a, b, c, d := 1, 2, 3, 4
    if a > 0 {
        if b > 0 {
            if c > 0 {
                if d > 0 {
                    fmt.Println("ok")
                }
            }
        }
    }
}

通过下面代码进行拆减

package main

import "fmt"

func main() {
    a, b, c, d := 1, 2, 3, 4

    // 直接通过一层 if 就进行判断,如果都大于 0 为真就直接打印 ok
    if a > 0 && b > 0 && c > 0 && d > 0 {
        fmt.Println("ok")
    }
}

1.4 if 接口 map 判断值是否存在

在 if 语句中我们还可以用来判断 map 的值是否存在。

package main

import "fmt"

func main() {
    m := make(map[int]string)
    m[1] = "111"

    // 这里是将 m[1] 的值赋值给了 v ,如果 m[1] 里面有值返回一个 bool
    if v, ok := m[1]; ok {
        fmt.Println(v)
    }

    // 也可以将其放到外面使用
    // 在程序中并没有对 m[2] 进行赋值所以返回给 ok 为 false
    v, ok := m[2]
    if ok {
        fmt.Println(v)
    } else {
        fmt.Printf("[%s]不存在\n", v)
    }
}

输出

[11:20:44 root@go day2]#go run main.go 
111
[]不存在

2 switch语句


– 首先代码从表达式开始执行,如果这个表达式和 case 中的第一个表达式匹配了就为 true 就执行语句块一,执行完毕之后就直接结束 switch 继续执行其他代码。
– 如果我们的表达式进入和第一个 case 中的表达式一匹配为假就回去看第二个 case ,然后又和第二个 case 中的表达式进行匹配,如果匹配成功执行语句块 2 ,然后switch语句执行结束就回去执行其他代码。
– 如果第二个 case 中的表达式没有和我们初始的表达式匹配成功就会又去匹配后面的多个 case 语句,如果 n 个 case 之后匹配成功就执行语句块 n 然后退出switch 语句。
– 如果都没有和我们的 case语句匹配上就会直接执行 default 语句块,然后最后也结束 switch 语句

switch执行流程总结:

  1. 先执行表达式,计算出之后得到值,然后和后面 case 的表达式进行比较,如果相当就匹配成功,然后执行对应的 case 中的语句块,然后结束 switch控制结构
  2. 如果switch 的表达式的值没有和任何 case 的表达式匹配成功,则执行 default语句块,最后退出switch控制结构
  3. golang 中的 case 后表达式可以有多个,使用 逗号 间隔
  4. 在 golang 中 case 后面不需要加 break ,因为默认就有,即在默认情况下当程序执行完一个 case语句块后,就直接退出该 switch 控制结构
  • switch-case-default 可能模拟 if-else if-else ,但只能实现相等判断
  • switch 和 case 后面可以跟常量、变量或函数表达式,只要它们表示的数据类型相同就行
  • case 后面可以跟多个值,只要有一个值满足就行
color := "black"

// 如果 case 变量和 switch 中的变量相等的话就类似 if 判断
switch color {
    case "green" :          // 相当于  if color== "green"
        fmt.Println("go")
    case "red" :            // 相当于 else if color== "red" 
        fmt.Println("stop")
    default:                // 相当于 else 
        fmt.Printf("invalid traffic signal: %s\n", strings.ToUpper(color))
}

switch 代码演示

package main

import "fmt"

func main() {
    color := "yellow"
    switch color {
    case "red":
        fmt.Println("color is red")
    case "green":
        fmt.Println("green")
    case "black":
        fmt.Println("black")
    default:
        fmt.Println("default")
    }
}

// 由于在 switch 的 case 中没有 yellow 所以输出 default 语句块里的内容
[15:13:16 root@go day2]#go run main.go 
default

switch 中调用函数代码演示

package main

import "fmt"

// 定义 add 函数返回值为 int
func add(a int) int {
    return a + 1
}

func main() {
    // 定义 a 变量值为 10
    a := 10

    // switch 做判断返回的值是否和 case 匹配
    switch add(a) {
    case 5:
        fmt.Println("sum is 5")
    case 10:
        fmt.Println("sum is 10")
    case 11:
        fmt.Println("sum is 11")
    default:
        fmt.Println("default")
    }
}

[15:13:20 root@go day2]#go run main.go 
sum is 11

switch 匹配多个条件

在 switch 中可以匹配多个条件进行判断

package main

import "fmt"

func main() {
    a, b := 10, 12
    switch a {

    // 这里多个条件匹配,只要命中一次就可以匹配
    case a, b, 10:
        fmt.Println("a, b, 10")
    case 1, 2, 3:
        fmt.Println("1,2,3")
    }
}

[16:19:22 root@go day2]#go run main.go 
a, b, 10

2.1 空 switch

  • switch 后带表达式时,switch-case 只能模拟相等的情况;如果 switch 后不带表达式,case 后就可以跟任意的条件表达式
// 当我们 switch 后面没有任何表达式时,可以随便写我们 case 表达式
// 例如下面案例是一个 大小于 的判断
switch {
case add(5) > 10:
    fmt.Println("right")
default:
    fmt.Println("wrong")
}

代码演示:

package main

import "fmt"

func main() {
    // 当我们 switch 为空的时候下面的 case 就是用于 if 判断,直接比较
    switch {
    case 1 == 2:
        fmt.Println("1=2")
    case 20 > 19:
        fmt.Println("20 > 19")
    default:
        fmt.Println("default")
    }
}

[16:24:49 root@go day2]#go run main.go 
20 > 19

2.2 switch Type(类型断言)

switch type 关系一个变量类型的判断,与 interface 使用较多,空接口接收任何类型

// 相当于在每个case内部申明了一个变量value
switch value := num.(type) { 

    // value已被转换为int类型
    case int: 
        fmt.Printf("number is int %d\n", value)

    // value已被转换为float64类型
    case float64: 
        fmt.Printf("number is float64 %f\n", value)

    // 如果case后有多个类型,则value还是interface{}类型
    case byte, string: 
        fmt.Printf("number is inerface %v\n", value)
}

范例代码:

package main

import "fmt"

func switchType() {
    // 定义 Ntype 变量类型为空接口类型并赋值为 1.1
    var Ntype interface{} = 1.1

    // 类型断言,通过 case 判断 Ntype 变量的类型
    switch Ntype.(type) {
    case int:
        fmt.Println("int")
    case string, byte:
        fmt.Println("string,byte")
    case float64:
        fmt.Println("float64")
    }

    // 也可以通过赋值的方式进行类型转换然后在 case 进行判断
    switch value := Ntype.(type) {
    case int:
        fmt.Printf("%v type is int \n", value)
    case string:
        fmt.Printf("%v type is string\n", value)
    case float64:
        fmt.Printf("%v type is float64\n", value)
    }
}

func main() {
    switchType()
}

[17:51:59 root@go day2]#go run main.go 
float64
1.1 type is float64

2.3 fallthrough

  • 从上往下,只要找到成立的 case,就不再执行后面的 case 了。所以为提高性能,把大概率会满足的情况往前放
  • case 里如果带了 fallthrough ,则执行完本 case 还会去判断下一个 case 是否满足
  • 在 switch type 语句的 case 子句中不能使用 fallthrough

代码演示:

package main

import "fmt"

func fall(age int) {
    switch {
    case age > 50:
        fmt.Println("age > 50")
        fallthrough
    case age > 25:
        fmt.Println("age > 25")
        fallthrough
    case age > 22:
        fmt.Println("age > 22")
        fallthrough
    case age > 18:
        fmt.Println("age > 18")
        fallthrough

    // 由于下面除了该 case 就没有其他的 case ,所以不能添加 fallthrough
    case age > 16:
        fmt.Println("age > 16")
    }
}

func main() {
    fall(30)
}

# 执行会发现即使当我们的 case 满足之后他依旧会继续往下匹配对应的 case
[16:39:40 root@go day2]#go run main.go 
age > 25
age > 22
age > 18
age > 16

3 for 循环

基本介绍:听其名而知其意,就是让你的代码可以循环的执行

  • 初始化变量可以放在 for 上面
  • 后续操作可以放在 for 块内部
  • 只有条件判断时,前后的分号可以不要
  • for{} 是一个无限循环

for 循环控制语法

for 循环变量初始化 ; 循环条件 ; 循环变量迭代 {
        循环操作(语句)
}

对上面的语法格式说明:

  • for 循环来说有四个要素
    • 1、循环变量初始化。(也就是说我们需要一个循环变量的初始化)
    • 2、需要一个循环条件。(所谓循环条件就是用来判断这个循环是否还能够继续执行)
    • 3、循环操作也可以叫做我们的循环体。(循环体就是我们需要具体做的事情)
    • 4、循环变量的迭代。

看下面伪代码:

arr := []int{1, 2, 3, 4, 5}
for i := 0; i < len(arr); i++ { // 正序遍历切片
    fmt.Printf("%d: %d\n", i, arr[i])
}

// for 初始化局部变量;条件表达式;后续操作。局部变量指仅在for块内可见
// for sum, i := 0, 0; i < len(arr) && sum < 100; sum, i = sum*1, i+1

for 循环执行的顺序分析:

  1. 首先执行循环变量初始化。如上面的范例代码中就是先执行 i:= 1
  2. 第二步执行循环条件的判断,比如 i <= len(arr)
  3. 如果循环条件判断为真就执行我们的循环操作,如上面的代码就是输出fmt.Printf("%d: %d\n", i, arr[i])
  4. 再执行我们的循环变量迭代,如上代码中的 i++
  5. 反复执行 2、3、4 步骤,知道循环条件为假时就退出 for 循环

代码演示:

package main

import (
    "fmt"
)

func v1() {
    arr := []int{1, 2, 3, 45}

    // 下面这三种 for 循环时等价的
    for i := 0; i < len(arr); i++ {
        fmt.Println(arr[i])
    }

    fmt.Println("===============>>>>")
    for i := 0; i < len(arr); {
        fmt.Println(arr[i])
        i++
    }

    // 但是这种 for 循环他的变量在 for 的外面
    fmt.Println("===============>>>>")
    i := 0
    for i < len(arr) {
        fmt.Println(arr[i])
        i++
    }
}

func main() {
    v1()
}

[14:17:31 root@go day2]#go run main.go 
1
2
3
45
===============>>>>
1
2
3
45
===============>>>>
1
2
3
45

for 循环流程分析


– 首先我们的代码从循环变量初始化开始执行,也就是上面范例代码的 i:=1
– 接着执行循环条件的判断,如果为真就执行循环操作
– 循环操作执行完了之后接着就是循环变量的迭代,如上范例代码i++
– 如果当我们的循环条件为假的时候,直接终止我们的 for 循环结束
– for 循环结束之后继续往下,如果下面还有代码就执行代码,如果下面没有代码了就相当于整个程序执行完毕

如果我们这个循环条件一直不为假,也就是一个死循环 for 循环就会一直循环

注意:

  • 循环条件是返回一个布尔值的表达式
    • 也就是说我们的循环体中返回的是一个布尔值的表达式,因为它是一个循环条件因此返回的一定是布尔值
    • 不管循环条件有多么复杂只要求我们的循环条件是真或者为假

3.1 for 循环复杂场景

如下代码

package main

import "fmt"

func v1() {
    arr := []int{1, 2, 3, 45}

    dp := 0
    // 在 for 循环的同时可以初始化多个变量,并且在进行循环条件的时候还能够通过判断
    // 比如 i 小于并且 sum 小于一百
    for sum, i := 0, 0; i < len(arr) && sum < 100; i++ {
        sum += arr[i]

        // 最终将获取到的 sum 总值赋值给 dp
        dp = sum
    }
    fmt.Println(dp)
}

func main() {
    v1()
}

[14:29:21 root@go day2]#go run main.go 
51

3.2 for-range

  • Golang 提供 for-range 的方式,可以方便遍历字符串和数组

  • 遍历字符串有两种方式

    • 一:最传统的方式

    • 二:就是通过 for-range 的方式来进行字符串的遍历

// 遍历数组或切片,i 为下标、ele 为该数组的值
for i, ele := range arr 

// 遍历 string
for i, ele := range "我会唱ABC"    // ele 是 rune 类型

// 遍历 map,go 不保证遍历的顺序
for key, value := range m

// 遍历 channel,遍历前一定要先 close
for ele := range ch
for range       // 拿到的是数据的拷贝

3.2.1 遍历数组或切片

package main

import "fmt"

func arr() {
    arr := [...]int{1, 2, 3, 4, 5, 6}
    for i, v := range arr {
        fmt.Printf("index=%d value=%v \n", i, v)
    }
}

func main() {
    arr()
}

[14:53:43 root@go day2]#go run main.go 
index=0 value=1 
index=1 value=2 
index=2 value=3 
index=3 value=4 
index=4 value=5 
index=5 value=6 

3.2.2 _ 占位符

当然如果只是想要 index 或者只想要 value 的话我们可以通过 _ 占位符

package main

import "fmt"

func arr() {
    arr := [...]int{1, 2, 3, 4, 5, 6}

    // 只想获取 value
    for _, v := range arr {
        fmt.Printf("value=%v \n", v)
    }

    // 只想获取 index
    for i, _ := range arr {
        fmt.Printf("index=%d \n", i)
    }
}

func main() {
    arr()
}

[14:57:21 root@go day2]#go run main.go 
value=1 
value=2 
value=3 
value=4 
value=5 
value=6 
index=0 
index=1 
index=2 
index=3 
index=4 
index=5 

3.2.3 遍历管道

package main

import "fmt"

func channel() {
    // 定义管道
    channel := make(chan int, 10)

    // 往管道中写入数据
    for i := 0; i < 10; i++ {
        channel <- i
    }

    // 在遍历管道前一定要关闭管道
    close(channel)

    // 通过 for-range 遍历
    for v := range channel {
        fmt.Println(v)
    }
}

func main() {
    channel()
}

3.2.4 遍历 string

package main

import "fmt"

func str() {
    str := "我会唱歌跳舞"

    fmt.Println(len(str))

    for i, v := range str {
        fmt.Printf("i=%d,s=%c\n", i, v)
    }
}

func main() {
    str()
}

[15:15:23 root@go day2]#go run main.go 
18                       # 一个中文占用 3 个字节
i=0,s=我                 # 并且我们可以看到对应的 index 下标每次增长都是以 3 的倍数进行增加
i=3,s=会
i=6,s=唱
i=9,s=歌
i=12,s=跳
i=15,s=舞

3.2.5 遍历 map

在遍历 map 的时候,顺序是不确定的,因为它并不能像切片、数组、管道、string 一样

因为 map 本身可以将其想象成一个环

package main

import "fmt"

func m() {
    // 定义 map
    m := map[int]int{1: 1, 2: 2, 3: 3, 4: 4}

    // k 获取的就是 map 的 key、v 获取的就是该 map k 对应的 value
    for k, v := range m {
        fmt.Printf("k=%d , v=%d \n", k, v)
    }
}

func main() {
    m()
}

[15:21:59 root@go day2]#go run main.go 
k=1 , v=1 
k=2 , v=2 
k=3 , v=3 
k=4 , v=4 

3.3 for 嵌套

多层 for 循环嵌套

在实际开发中会遇到一些比较复杂的业务逻辑,这个时候就需要多重循环控制才能够被解决。

多重循环介绍(重点难点)

  • 将一个循环放在另一个循环体内,就形成了嵌套循环。在外边的 for 称为外层循环,在里面的 for 循环称为内层循环。【建议一般使用两层,最多不要超过3层】
  • 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。
  • 设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n=mn次。

如下面伪代码:

当我们需要遍历二位数组的时候就使用到

// 定义常量 size
const SIZE = 4

// 定义 A 二位数组
A := [SIZE][SIZE]float64{}

// 两层for循环嵌套
for i := 0; i < SIZE; i++ {
    for j := 0; j < SIZE; j++ {
        A[i][j] = rand.Float64() //[0,1)上的随机数
    }
}

4 break与continue

  • break 与 continue 用于控制 for 循环的代码流程,并且只针对最靠近自己的外层 for 循环
  • break 退出 for 循环,且本轮 break 下面的代码不再执行
  • continue 本轮 continue 下面的代码不再执行,进入 for循环的下一轮

4.1 break

break 语句用于终止某个语句块的执行,用于中断当前 for 循环或者退出 switch 语句。

基本语法

{
......
    break
......
}


如果我们的代码在某个情况下进入到了 break 语句了,这时就不会再去进行 for 循环变量的迭代。假如在 if 这里条件为真就执行了 break 语句,如果执行了 break 就直接退出 for 循环去执行其他代码

代码演示:

看下面一个需求:

随机生成 1-100 的一个数,直到生成了 99 这个数,看看你一共用了几次?

分析:

这个题最好的方案就是写一个无限循环,然后随机循环当出现了 99 这个数的时候就退出无限循环。

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func read99() {
    count := 0

    // 通过死循环
    for {

        // 定义随机数种子
        rand.Seed(time.Now().UnixNano())
        // 100 以内的随机数
        n := rand.Intn(100)
        count++
        if n == 99 {
            fmt.Println(n)
            // 如果 n=99 直接 break 退出 for
            break
        }
    }
    fmt.Println()
    fmt.Println(count)
}

func main() {
    read99()
}

[11:02:50 root@go day2]#go run main.go 
99

102

4.2 break 和 table

break 语句出现在多层嵌套的语句块时,可以通过标签指明要终止的是那一层语句块 什么意思呢请看下面的这串代码:

// 也就是说我们的 break 也有可能是放在嵌套的 for 循环里面的或者是嵌套的 switch 里面的 ,下面代码一旦当 break 遇到 label2 就直接跳出 label2 这一层 ,进入到 label1 这层,如果我们在 break 后面写的是 label1 这一层等于说直接跳出整个 label1 这一层也就说所有的 label 层都不在循环。

label1: {......
label2:     {......
label3:         {......
                    break label2;
                }
            }
        }

4.2.1 table 在循环体内部

代码演示:

package main

import "fmt"

func break_table() {
    for i := 0; i < 2; i++ {
        fmt.Println("i=", i)
    t1:                         // 定义 t1 标签,这个标签名字可以自定义
        for j := 0; j < 10; j++ {
            if j == 2 {
                break t1        // 当 j == 2 的时候就 break 到 t1
            }
            fmt.Println("j=", j)
        }
    }
}

func main() {
    break_table()
}

可以看到每次内循环中 j 的值不会大于 2 ,直到 i 循环完了 j 也只是 0 、1

[11:09:20 root@go day2]#go run main.go 
i= 0
j= 0
j= 1
i= 1
j= 0
j= 1

4.2.2 table 在循环体外

如果说我们的 table 标签是在循环体外的话,就可以直接退出当前 for 循环

package main

import "fmt"

func break_table() {
t1:         // 定义 t1 标签
    for i := 0; i < 10; i++ {
        fmt.Println(i)
        if i == 5 {     // 如果 i==5 就执行 break t1 跳出当前 for 循环
            break t1
        }
    }
}

func main() {
    break_table()
}

输出

[11:13:12 root@go day2]#go run main.go 
0
1
2
3
4
5

总结:对上面案例的说明

  • break 默认会跳出最近的循环,如果是 switch 也是一个道理。
  • break 可以配合标签使用,可以指定跳出那一层标签指定的 for 循环

4.3 跳转控制语句-continue

  • continue 语句是用于结束本次循环,继续执行下一次循环。
  • continue 语句可以出现在多层嵌套的循环语句中,可以通过标签指明要跳过的那一层循环,这个和 break 标签的使用规则是一样的。

基本语法:

{ ......
    continue
} ......

以 for 使用 continue 为例,画出示意图


如果在循环里面遇到了 continue ,那么下面的循环操作将不再执行,并不会结束整个 for 循环,而是结束本次 for 循环也就是下面的代码不在执行,就直接到循环变量迭代中去。进行下一次的循环判断

代码演示:

package main

import "fmt"

func test1() {
    for i := 0; i < 3; i++ {
        for j := 0; j < 4; j++ {
            // 每当 j == 3 的时候就直接 continue 跳出当前这次循环,执行下一次循环
            if j == 3 {
                continue
            }
            fmt.Println("j=", j)
        }
    }
}

func main() {
    test1()
}
[11:19:38 root@go day2]#go run main.go 
j= 0
j= 1
j= 2
j= 0
j= 1
j= 2
j= 0
j= 1
j= 2

# 可以通过输出看到每次输出都不会将 j = 3 的输出,因为直接跳出而执行了下一次循环

5 跳转控制语句 goto

1) Go 语言的 goto 语句可以无条件地转移到程序中指定的行。也就是说可以通过标签就可以指定跳转到任意一个位置
2) goto 语句通常与条件语句配合使用。可用来实现条件转移,跳出循环体等功能。(一般和 if 语句配合)
3) 在Go程序设计中一般不主张使用 goto 语句goto 语句容易造成程序流程的混乱,使理解和调试程序都产生困难

建议:在编程中能不用 goto 就不用 goto 语句了

基本语法:

goto label
...
label:statement

我们先自定义一个 label ,当我们的程序执行到 goto 的时候就会发现后面跟了一个 label ,就会跳过下列 … 的代码,也就是说 … 这个块的代码就不执行了。直接就跳转到 lable 这个位置去执行。

代码演示:

package main

import "fmt"

func test1() {
    fmt.Println("ok1")
    // 执行完了 ok1 直接跳到 t1 标签进行执行下面的代码,所以这里 ok2 和 ok3 不再输出
    goto t1
    fmt.Println("ok2")
    fmt.Println("ok3")
t1:
    fmt.Println("ok4")
    fmt.Println("ok5")
    fmt.Println("ok6")
    fmt.Println("ok7")
}

func main() {
    test1()
}

[11:24:14 root@go day2]#go run main.go 
ok1
ok4
ok5
ok6
ok7

代码演示2:

package main

import "fmt"

func test1() {
    n := 20
    fmt.Println("1")
    // 这里判断 n 是否大于 20 ,而上面我们定义了 n=20 所以这里的 goto 不会执行
    if n > 20 {
        goto t1
    }
    fmt.Println("2")
    fmt.Println("3")
t1:
    fmt.Println("4")
}

func main() {
    test1()
}

# 由于没有执行 goto 所以会将所有的代码执行
[11:25:05 root@go day2]#go run main.go 
1
2
3
4

6 return

return 使用在方法或者函数中,表示跳出所在的函数或者方法。

  • 如果 return 是在普通的函数,则表示跳出该函数,即不再执行函数中 return 后面的代码,也可以理解成终止该函数
  • 如果 return 是在这个 main 函数就表示这个程序都整个退出了,因为 main 函数一个程序的主入口。如果说 main 函数都退出了就表示终止整个程序了

6.1 return 放在普通函数中

范例演示

当 return 放在普通函数中。直接退出 test1 函数而继续执行 main 函数中剩下的代码

package main

import "fmt"

func test1() {

    for i := 0; i < 10; i++ {
        fmt.Println(i)
        // 如果当 i == 5 的时候就直接 return 退出 test1 函数
        if i == 5 {
            return
        }
    }
}

func main() {
    test1()
    fmt.Println("main")
}

[11:35:06 root@go day2]#go run main.go 
0
1
2
3
4
5
main                    # 执行 main 函数中剩余的代码

6.2 return 放在 main 函数中

如果我们将 return 放在 main 函数中执行,就会直接退出程序

package main

import "fmt"

func main() {
    fmt.Println("test")
    // 输出了 test 就不会执行 main 函数下面其他的代码程序
    return
    fmt.Println("main")
}

[11:58:53 root@go day2]#go run main.go 
test

所以如果说 return 放到 main

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇