分支结构
if...else...语句
Go 语言中的 if...else
语句是一种基本的流程控制结构,用于根据条件执行不同的代码块。下面是关于 Go 语言中 if...else
语句的详细介绍:
基本语法
Go
if 条件表达式 {
// 当条件表达式为 true 时执行的代码
} else {
// 当条件表达式为 false 时执行的代码
}
用法
1.基本的 if 语句
Go
if score > 60 {
fmt.Println("Pass")
}
2.if...else...语句
Go
var ten int = 11
if ten > 10 {
fmt.Println(">10")
} else {
fmt.Println("<=10")
}
3.if...else if...else 链
Go
if score >= 90 {
fmt.Println("Excellent")
} else if score >= 60 {
fmt.Println("Pass")
} else {
fmt.Println("Fail")
}
特殊写法
if 还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断,代码如下:
Go
if num, err := someFunction(); err == nil {
fmt.Println(num)
} else {
fmt.Println(err)
}
这段代码是Go语言中一个非常典型的模式,用于处理那些可能会返回错误的情景,比如读取文件、网络操作或调用某些可能失败的函数。我来详细解释一下每一部分:
-
函数调用与同时声明变量:
1num, err := someFunction()
这一行做了两件事:
- 调用了
someFunction()
函数。 - 使用简短声明
:=
同时声明了两个变量num
和err
,并分别赋予了someFunction()
返回的两个值。在Go中,一个函数可以返回多个值,这里假设someFunction()
返回一个需要的数据(例如一个整数、字符串等,用num
接收)和一个错误对象(用err
接收)。如果函数执行成功,通常会返回nil
作为错误值。
- 调用了
-
条件判断:
Goif err == nil {
这个条件检查
err
是否为nil
。在Go中,nil
表示没有错误,所以如果err == nil
为真,意味着someFunction()
调用成功。 -
成功分支:
Gofmt.Println(num)
如果没有错误(即
err == nil
),就打印出成功获取到的数据num
。 -
失败分支:
Goelse { fmt.Println(err) }
如果有错误(即
err != nil
),则执行这里的代码块,打印出错误信息。这样可以快速定位问题所在。
循环结构
for语句
for
循环的几种主要形式:
1.经典C风格的for循环:
Go
for 初始化; 条件; 更新 {
// 循环体
}
这种形式类似于C语言的for循环,其中:
- 初始化:在循环开始之前执行一次,通常用于设置循环控制变量。
- 条件 :在每次循环迭代前检查,如果为
true
则执行循环体。 - 更新:在每次循环体执行完毕后执行,通常用于改变循环控制变量。
用法
Go
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
2.条件循环:
Go
for 条件 {
// 循环体
}
这种形式省略了初始化和更新部分,仅当给定的条件为 true
时执行循环体,相当于没有初始化和更新的简化版。
用法
Go
var i int
for i <= 10 {
i++
}
3.无限循环:
Go
for {
// 循环体
}
这种形式没有条件检查,因此会一直循环下去,除非在循环体内使用 break
语句跳出循环。
用法
Go
var i int
for {
if i > 10 {
break
}
i++
}
Go
for j := 0; j < 5; j++ {
for i := 0; i < 10; i++ {
if i > 5 {
break JLoop
}
fmt.Println(i)
}
}
JLoop:
// ...
上述代码中,break 语句终止的是 JLoop 标签处的外层循环。
4.for 中的初始语句------开始循环时执行的语句
初始语句是在第一次循环前执行的语句,一般使用初始语句执行变量初始化,如果变量在此处被声明,其作用域将被局限在这个 for 的范围内。
初始语句可以被忽略,但是初始语句之后的分号必须要写,代码如下:
Go
step := 2
for ; step > 0; step-- {
fmt.Println(step)
}
这段代码将 step 放在 for 的前面进行初始化,for 中没有初始语句,此时 step 的作用域就比在初始语句中声明 step 要大。
5.for 中的条件表达式------控制是否循环的开关
每次循环开始前都会计算条件表达式,如果表达式为 true,则循环继续,否则结束循环,条件表达式可以被忽略,忽略条件表达式后默认形成无限循环。
结束循环时带可执行语句的无限循环
下面代码忽略条件表达式,但是保留结束语句,代码如下:
Go
var i int
for ; ; i++ {
if i > 10 {
break
}
}
上面的代码还可以改写为更美观的写法,代码如下:
Go
var i int
for {
if i > 10 {
break
}
i++
}
练习题:打印九九乘法表
Go
package main
import "fmt"
func main() {
// 遍历, 决定处理第几行
for y := 1; y <= 9; y++ {
// 遍历, 决定这一行有多少列
for x := 1; x <= y; x++ {
fmt.Printf("%d*%d=%d ", x, y, x*y)
}
// 手动生成回车
fmt.Println()
}
}
键值循环
在Go语言中,for
循环有一种特殊形式,称为"键值循环"(key-value iteration),常用于遍历数组、切片、映射(map)、通道(channel)等集合类型,特别是当需要同时访问元素的索引或键以及对应的值时。这种循环形式使用关键字range
。
基本语法
Go
for index, value := range collection {
// 循环体
}
其中:
index
:表示集合中当前元素的索引或映射中键的副本。value
:表示集合中当前元素的值或映射中对应键的值的副本。collection
:是要遍历的集合,可以是数组、切片、映射或通道。
遍历数组/切片
示例1:遍历切片
Go
package main
import "fmt"
func main() {
fruits := []string{"apple", "banana", "cherry"}
for i, fruit := range fruits {
fmt.Printf("Index: %d, Fruit: %s\n", i, fruit)
}
}
这段代码会输出每个元素的索引和值。
示例2:忽略索引
如果你不关心索引,可以使用下划线 _
忽略它。
Go
for _, fruit := range fruits {
fmt.Println(fruit)
}
遍历映射(map)
示例3:遍历映射
Go
package main
import "fmt"
func main() {
ages := map[string]int{"Alice": 30, "Bob": 25, "Charlie": 35}
for name, age := range ages {
fmt.Printf("%s is %d years old.\n", name, age)
}
}
这里,name
是键,age
是值。
示例4:仅遍历映射的键或值
如果你想只获取映射的键或值,可以再次使用下划线 _
。
Go
for name := range ages {
fmt.Println(name)
}
// 或
for _, age := range ages {
fmt.Println(age)
}
遍历通道
示例5:遍历通道
Go
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go func() {
for i := 0; i < 5; i++ {
ch <- i
time.Sleep(time.Second)
}
close(ch)
}()
for v := range ch {
fmt.Println("Received:", v)
}
}
在这个例子中,range
用于从通道接收值,直到通道被关闭。