王清欢Randy 王清欢Randy
首页
  • 编程语言

    • C/C++ 学习笔记
    • Golang 学习笔记
  • 算法分析

    • LeetCode 刷题笔记
  • 操作系统

    • Linux 基础
    • Vim 实用技巧
    • Shell 脚本编程
    • GDB 学习笔记
  • 开发工具

    • Git 学习笔记
  • 分布式理论

    • 共识算法
    • 分布式事务
  • 数据库内核

    • PostgreSQL
    • Postgres-XL
  • hidb
  • pgproxy
  • 实用技巧
  • 学习方法
  • 资源分享
GitHub (opens new window)
首页
  • 编程语言

    • C/C++ 学习笔记
    • Golang 学习笔记
  • 算法分析

    • LeetCode 刷题笔记
  • 操作系统

    • Linux 基础
    • Vim 实用技巧
    • Shell 脚本编程
    • GDB 学习笔记
  • 开发工具

    • Git 学习笔记
  • 分布式理论

    • 共识算法
    • 分布式事务
  • 数据库内核

    • PostgreSQL
    • Postgres-XL
  • hidb
  • pgproxy
  • 实用技巧
  • 学习方法
  • 资源分享
GitHub (opens new window)
  • Golang基础

    • 数据类型

      • 变量与常量
      • 基础数据类型之值类型
      • 基础数据类型之引用类型
    • 流程控制

      • 条件判断
      • 循环控制
        • 01 基础循环 for
        • 02 键值循环 for range
        • 参考资料
    • 函数

      • 函数基础
      • 匿名函数与闭包
      • 延迟调用
  • Golang学习笔记
  • Golang基础
  • 流程控制
王清欢
2023-03-24
目录

循环控制

# 循环控制

循环控制通常用于程序中需要重复执行的逻辑模块,循环结构通常由循环变量、循环终止条件和循环体三个部分构成。

# 01 基础循环 for

Golang 中所有的循环控制都使用 for 关键定义。基础 for 循环控制结构,可以执行指定次数的循环,一般形式是 for init; condition; post { body },其中:

  • init:一般为赋值表达式,给控制变量赋初值;
  • condition: 关系表达式或逻辑表达式,循环控制条件;
  • post: 一般为赋值表达式,给控制变量增量或减量
  • body:是需要重复执行的循环体代码

init 的循环变量同样存在作用域问题,在 for 循环中声明的变量仅在该循环体内有效,对外部变量没有影响;如果引用了外部声明的变量,则该循环变量具有更大的作用域。

func ForExp() {
    var i int = 10
    for i := 0; i < 9; i++ {
        fmt.Printf("%d ", i)
    }
    fmt.Printf(" global i: %d\n", i)
}

/* output:
0 1 2 3 4 5 6 7 8  global i: 10
*/

while 循环:Golang 中并没有 while 关键字,可以使用只有一个循环条件的 for 循环语句实现类似的功能,在循环体外部声明循环遍历,满足循环条件时循环执行循环体。

func ForExp() {
    var i int = 10
    for i > 0 {
        i--
        fmt.Printf("%d ", i)
    }
    fmt.Printf(" global i: %d\n", i)
}

/* output:
9 8 7 6 5 4 3 2 1 0  global i: 0
*/

无限循环:其他语言中无限循环大多使用 while(true) 实现,在 Golang 中使用不带循环变量和循环条件的 for{} 实现。无限循环在需要时可以使用 break 跳出循环。

func ForExp() {
    var i int = 10
    for {
        i--
        fmt.Printf("%d ", i)
        if i == 0 {
            break
        }
    }
    fmt.Printf(" global i: %d\n", i)
}

/* output:
9 8 7 6 5 4 3 2 1 0  global i: 0
*/

循环嵌套:在 for 循环中嵌套一个或多个 for 循环实现更复杂的循环执行逻辑。

循环嵌套中常常使用 goto、break、continue 三种循环控制关键字结合代码标签进行循环跳出或程序执行位置的调整

  • goto 语句通过标签进行代码间的无条件跳转,可以在快速跳出循环、避免重复退出上有一定的帮助。
  • break 语句可以结束 for、switch 和 select 的代码块;还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的for、switch和select的代码块上。
  • continue 语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for循环内使用;在continue语句后添加标签时,表示开始标签对应的循环。
func ForExp() {
Prime: // 外层循环标签
    for i := 2; i < 100; i++ {
        j := 2
        for ; j <= (i / j); j++ {
            if i%j == 0 {
                break Prime // 退出循环到 Prime 之外
            }
        }
        if j > (i / j) {
            fmt.Printf("%d  是质数\n", i)
        }
    }
}

# 02 键值循环 for range

Golang 中提供 for range 遍历数组、切片、字符串、键值对(map)和通道(channel)等容器,不同容器的返回值也有所不同;对于仅需获得一个返回值的应用场景可以直接使用匿名变量 _接收不需要的返回值。

第一个返回值 第二个返回值
array/slice/string index s[index]
map key m[key]
channel element
  • 数组、切片、字符串返回索引和元素值
  • 键值对(map)返回键和值
  • 通道(channel)只返回通道内的值

遍历数组、切片和字符串:for range 遍历数组、切片、字符串时,index 和 value 分别代表索引和索引值

func RangeExp() {
    var a = [5]int{1, 2, 3, 4, 5}
    var s []float32 = make([]float32, 3, 5)
    s = []float32{1.0, 2.0, 3.0}
    var str string = "hello,world!"
    fmt.Println("----------Array----------")
    for index, value := range a {
        fmt.Printf("index:%d, value:%d\n", index, value)
    }
    fmt.Println("----------Slice----------")
    for index, value := range s {
        fmt.Printf("index:%d, value:%f\n", index, value)
    }
    fmt.Println("----------String----------")
    for index, value := range str {
        fmt.Printf("index:%d, value:%c\n", index, value)
    }
}

/* output:
----------Array----------
index:0, value:1
index:1, value:2
index:2, value:3
index:3, value:4
index:4, value:5
----------Slice----------
index:0, value:1.000000
index:1, value:2.000000
index:2, value:3.000000
----------String----------
index:0, value:h
index:1, value:e
index:2, value:l
index:3, value:l
index:4, value:o
index:5, value:,
index:6, value:w
index:7, value:o
index:8, value:r
index:9, value:l
index:10, value:d
index:11, value:!
*/

遍历键值对 map:for range 遍历键值对 Map 时,key 和 value 分别代表 map 的索引键 key 和索引对应的值 value。值得注意的是对 map 遍历时,遍历输出的键值是无序的,如果需要有序的键值对输出,需要对结果进行排序。

func RangeExp() {
    hash := map[int]string{
        1: "one",
        2: "two",
        3: "three",
    }
    fmt.Println("----------Map----------")
    for key, value := range hash {
        fmt.Printf("key:%d, value:%s\n", key, value)
    }
}

/* output:
----------Map----------
key:1, value:one
key:2, value:two
key:3, value:three
*/

遍历通道 channel:for range 遍历通道 channel 时,返回值只有一个,即管道内的类型对应的数据。

func RangeExp() {
    c := make(chan int)
    go func() {
        c <- 1
        c <- 2
        c <- 3
        close(c)
    }()
    fmt.Println("----------Channel----------")
    for value := range c {
        fmt.Printf("value:%d\n", value)
    }
}

/* output:
----------Channel----------
value:1
value:2
value:3
*/

# 参考资料

循环语句for · Go语言中文文档 (opens new window)

循环语句range · Go语言中文文档 (opens new window)

Go语言 if判断和for循环实战 goto使用的那些坑 - 掘金 (opens new window)

上次更新: 2023/11/19, 12:55:48
条件判断
函数基础

← 条件判断 函数基础→

Theme by Vdoing | Copyright © 2023-2024 Wang Qinghuan | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式