当前位置: 首页 > news >正文

Golang语言基础篇006_Golang流程控制

流程控制是任何编程语言的核心组成部分,它决定了程序的执行路径。Go语言提供了丰富的流程控制语句,包括条件语句、循环语句和跳转语句,帮助开发者精确控制程序的执行流程。

1. 条件语句

1.1. if语句

Go语言中if条件语句的格式如下:

if 布尔表达式1 {// 布尔表达式1结果为true时执行
} else if 布尔表达式2 {// 布尔表达式1结果为false且布尔表达式2结果为true时执行
}else{// 前面的布尔表达式都为false时执行
}
  • else if 子语句可能没有,也可能又多个。
  • else 子语句可能没有,但不能有多个。
  • ifelse ifelse 子语句执行体内部都可以嵌套if条件语句

Go语言中不支持三目运算符!

示例:

// 基本if语句
if x > 0 {fmt.Println("x是正数")
}// if-else语句
if x > 0 {fmt.Println("x是正数")
} else {fmt.Println("x不是正数")
}// if-else if-else语句
if x > 0 {fmt.Println("x是正数")
} else if x < 0 {fmt.Println("x是负数")
} else {fmt.Println("x是零")
}

Go语言的if语句支持在条件判断前执行初始化语句:

// 在if语句中声明和初始化变量
if x := computeValue(); x > 10 {fmt.Printf("计算结果%d大于10\n", x)
} else {fmt.Printf("计算结果%d不大于10\n", x)
}// 注意:x的作用域仅限于if语句块内
// fmt.Println(x)  // 错误:未定义// 文件操作示例
if file, err := os.Open("test.txt"); err != nil {fmt.Println("打开文件失败:", err)
} else {defer file.Close()// 处理文件...
}

1.2. 基本switch语句

switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上直下逐一测试,直到匹配为止:

格式:

switch 外层表达式 {case 内层表达式1:// 内层执行体1case 内层表达式2:// 内层执行体2fallthroughcase 内层表达式3,内层表达式4:// 内层执行体3default:// 默认执行
}
  • 外层表达式和内层表达式都可以是任意类型,但需要保证两者的结果是同一种类型。

  • 当外层表达式和内层表达式的结果一致时,执行对应的结构体。

  • 同一个case后面可以有多个内层表达式,用,分隔。这表示当后面的任意表达式满足时,执行对应的内层执行体。

    上面的内层表达式3和内层表达式4,他们任意一个满足时,都会执行内层执行体3

  • 外层表达式可以忽略(等于switch true{…}),此时内层表达式只能为布尔表达式。当内层布尔表达式为true时执行对应的执行体。

  • 与Java不同,Go语言中的某个内层执行体执行完成后,默认不执行下一个内层执行体,如果需要执行下一个执行体,需要添加fallthrough关键字。

    上面的内层表达式1满足后,只会执行内层执行体1.

    内层表达式2满足后,会执行内层执行体2和内层执行体3.

  • default下的默认执行体,在上面的所有case条件都不成立的时候执行。

    default可以省略。

  • Go语言的switch语句支持在switch关键字后执行初始化语句。

示例:简单switch语句

// 基本switch语句
grade := "B"
switch grade {
case "A":fmt.Println("优秀")
case "B":fmt.Println("良好")
case "C":fmt.Println("一般")
default:fmt.Println("不及格")
}

示例:表达式switch

// case后面可以跟表达式
x := 5
switch {
case x < 0:fmt.Println("x是负数")
case x > 0 && x < 10:fmt.Println("x是个位正数")
case x >= 10:fmt.Println("x是两位或以上的正数")
}// switch后面可以跟表达式
x := 10
y := 0
switch x + y {
case 0:fmt.Println("0")
case 10:fmt.Println("10")
default:fmt.Println("default")
}// switch后面甚至可以初始化变量
x := 10
y := 0
switch r := x + y; r >= 0 {
case true:fmt.Println("true")
case false:fmt.Println("false")
default:fmt.Println("default")
}

示例:多条件匹配

// 一个case可以匹配多个值
ch := 'a'
switch ch {
case 'a', 'e', 'i', 'o', 'u':fmt.Println("元音字母")
case 'b', 'c', 'd', 'f', 'g':fmt.Println("辅音字母")
default:fmt.Println("其他字符")
}

示例:fallthrough关键字

// fallthrough会执行下一个case,即使条件不满足
x := 10
switch x {
case 10:fmt.Println("等于10")fallthrough  // 继续执行下一个case
case 20:fmt.Println("等于20或执行了fallthrough")
case 30:fmt.Println("等于30或执行了fallthrough")
default:fmt.Println("其他值")
}
// 输出:
// 等于10
// 等于20或执行了fallthrough

1.3. 类型switch

switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。

typw-switch语句算是switch语句的一个变种

语法格式:

switch 接口变量.(type){case 类型1:// 执行体1case 类型2:// 执行体2default:// 默认执行体
}

示例:

// 类型switch用于判断接口变量的具体类型
func processValue(v interface{}) {switch val := v.(type) {case int:fmt.Printf("整数: %d\n", val)case string:fmt.Printf("字符串: %s\n", val)case bool:fmt.Printf("布尔值: %t\n", val)case nil:fmt.Println("空值")default:fmt.Printf("未知类型: %T\n", val)}
}func main() {processValue(42)processValue("Hello")processValue(true)processValue(nil)
}

1.4. select语句

select 是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收。 select 随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该总是可运行的。

语法格式:

select {case communication clause  :// statement(s)      case communication clause  :// statement(s)/* 你可以定义任意数量的 case */default : /* 可选 */statement(s)
}
  • 每个case都必须是一个通信操作.
  • 如果任意某个通信操作可以进行,它就执行;其他被忽略。
  • 如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。
  • 当没有任何通信操作可以执行时,如果有default子句,则执行该语句。如果没有default字句,select将阻塞,直到某个通信可以运行。

在一个select语句中,Go会按顺序从头到尾评估每一个发送和接收的语句。

如果其中的任意一个语句可以继续执行(即没有被阻塞),那么就从那些可以执行的语句中任意选择一条来使用。 如果没有任意一条语句可以执行(即所有的通道都被阻塞),那么有两种可能的情况:

①如果给出了default语句,那么就会执行default的流程,同时程序的执行会从select语句后的语句中恢复。

②如果没有default语句,那么select语句将被阻塞,直到至少有一个case可以进行下去。

示例:

// 基本select语句
ch1 := make(chan string)
ch2 := make(chan string)go func() {time.Sleep(1 * time.Second)ch1 <- "来自通道1的消息"
}()go func() {time.Sleep(2 * time.Second)ch2 <- "来自通道2的消息"
}()// select会选择第一个准备好的case执行
select {
case msg1 := <-ch1:fmt.Println("收到:", msg1)
case msg2 := <-ch2:fmt.Println("收到:", msg2)
case <-time.After(3 * time.Second):fmt.Println("超时")
}

2. 循环语句

2.1. for语句

for循环是一个循环控制结构,可以循环循环执行指定次数或不限次数。

语法格式如下:

for 初始化子句;条件子句;后置子句{// 执行体
}

执行流程:

  1. 执行初始化子句
  2. 判断条件子句结果,如果为true继续执行,否则退出循环。
  3. 执行执行体
  4. 执行后置子句
  5. 自动跳转到第2步。

注意事项:

  • 初始化子句、条件子句、后置子句都可以为空。当初始化子句和后置子句都为空时,可以省略两个分号。
    • 初始化子句为空表示不执行初始化操作。
    • 后置子句为空表示不执行后置操作。
    • 条件子句为空默认为true。
  • for循环可以嵌套使用。

示例:基本for循环

// 传统的for循环
for i := 0; i < 5; i++ {fmt.Printf("循环次数: %d\n", i)
}

示例:while循环形式

// Go语言没有while关键字,但for可以实现相同效果
i := 0
for i < 5 {fmt.Printf("循环次数: %d\n", i)i++
}

示例:无限循环

// 无限循环
for {fmt.Println("无限循环")// 需要break或其他方式跳出循环break  // 或者return、goto等
}

2.2. for-range循环

range关键字用于遍历数组、切片、映射、字符串和通道:

  • 遍历数组/切片

    // 遍历数组或切片
    numbers := []int{1, 2, 3, 4, 5}
    for index, value := range numbers {fmt.Printf("索引%d: 值%d\n", index, value)
    }// 只获取索引
    for i := range numbers {fmt.Printf("索引: %d\n", i)
    }// 只获取值
    for _, value := range numbers {fmt.Printf("值: %d\n", value)
    }
    
  • 遍历映射

    // 遍历映射
    scores := map[string]int{"数学": 95,"语文": 87,"英语": 92,
    }for subject, score := range scores {fmt.Printf("%s: %d分\n", subject, score)
    }
    
  • 遍历字符串

    s := "Hello World"
    for i, c := range s {fmt.Printf("%d: %c\n", i, c)
    }
    for i := range s {fmt.Printf("%d: %c\n", i, s[i])
    }
    
  • 遍历通道

    // 定义通道
    c := make(chan int)// 启动一个单独的协程
    go func() {
    // 重复十次
    for i := 0; i < 10; i++ {// 睡眠1秒time.Sleep(time.Second)// 往通道写入数据c <- i
    }
    // 关闭通道
    close(c)
    }()// 遍历读取通道数据
    for i := range c {
    fmt.Println(i)
    }
    

3. 跳转语句

3.1. break

break关键字用于跳出当前循环语句或者switch语句。

3.1.1. 循环中使用

break关键字在循环体中使用,表示不执行后续操作,直接退出当前循环体。

循环体{// 前面的执行语句break// 后面的执行语句
}
  • break关键字执行后,关键字后面的执行语句不会被执行。
  • break关键字执行后,退出当前循环。
  • 如果break关键字在多重循环内,将退出的是break关键字所在的最内层循环。

示例:

func main() {a := []int{1, 2, 3, 4, 5}for i := 0; i < 5; i++ {for j, v := range a {fmt.Print(v)if j == i {break}}fmt.Println()}
}
// 结果:
1
12   
123  
1234 
12345

break关键字还可以搭配标签使用,表示退出标签后面紧跟的循环。

语法格式:

标签名字:    
循环1 {// 前置语句1循环2 {// 前置语句2break 标签名字// 后置语句2}// 后置语句1
}
  • 标签后面应该紧跟循环,不能再有其他语句。

  • break关键字执行后,关键字后面的执行语句不会被执行。

    如后置语句2、后置语句1

  • break关键字执行后,退出标签后面紧跟的循环。

3.1.2. switch中使用

break关键字在switch中使用,表示不执行后续操作,直接退出当前switch体。

语法格式:

switch语句{case子句{// 前面的执行语句break// 后面的执行语句}
}
  • break关键字执行后,关键字后面的执行语句不会被执行。
  • break关键字执行后,退出当前switch。
  • 如果break关键字在多重switch内,将退出的是break关键字所在的最内层switch。

示例:

func main() {var a = 1var b = 2switch a {case 1:fmt.Println(11)switch b {case 2:fmt.Println(21)if b > a {break}fmt.Println(22)}fmt.Println(12)}
}
// 结果
11
21
12

break关键字还可以搭配标签使用,表示退出标签后面紧跟的switch。

func main() {var a = 1var b = 2
label:switch a {case 1:fmt.Println(11)switch b {case 2:fmt.Println(21)if b > a {break label}fmt.Println(22)}fmt.Println(12)}
}
// 结果
11
21
  • 标签后面应该紧跟switch,不能再有其他语句。
  • break关键字执行后,关键字后面的执行语句不会被执行。
  • break关键字执行后,退出标签后面紧跟的switch。

3.2. continue语句

continue关键字用于停止当前循环体的执行,转而执行下一次循环。

语法格式:

for 初始化子句;条件子句;后置子句{// 执行体1continue// 执行体2
}
  • continue关键字只能在循环中使用。

  • continue关键字执行后,关键字后面的执行体不会执行。

    • 执行体2 不会被执行。
  • 如果continue关键字在多重循环体内,将作用在关键字所在的最内层循环。

示例:

func main() {a := []int{1, 2, 3}for i := range a {fmt.Print(i, "->")if i == 1 {fmt.Println("XXX")continue}fmt.Println(a[i])}
}
// 结果
0->1  
1->XXX
2->3  

continue关键字还可以搭配标签使用,表示作用于标签后面紧跟的循环。

语法格式:

标签名字:    循环1 {// 前置语句1循环2 {// 前置语句2continue 标签名字// 后置语句2}// 后置语句1}
  • 标签后面应该紧跟循环,不能再有其他语句。

  • continue关键字执行后,关键字后面的执行语句不会被执行。

    如后置语句2、后置语句1

  • continue关键字执行后,继续执行标签后面紧跟的循环。

3.3. goto语句

Go语言保留了goto语句,但建议谨慎使用。

goto必须搭配标签使用,表示跳转到标签所在的位置,并开始执行标签后的语句。

示例:

func main() {a := []int{1, 2, 3}count := 0
tag:for i := 0; i < len(a); i++ {fmt.Print(a[i])}fmt.Println()count++if count < 3 {goto tag}
}
// 结果
123
123
123
http://www.dtcms.com/a/403476.html

相关文章:

  • 襄樊网站网站建设网站建设中管理员登录的代码怎么写
  • 打工人日报#20250924
  • 网站的构思重庆建设工程造价信息
  • 【lua】luajit 命令行使用指南
  • 网站配置系统搭建一个网站需要多久
  • 绿联UGOS Pro九月更新,三端优化,影音相册再升级
  • JAVA学习-预科部分(路线、博客、预备基础)
  • 使用IDEA创建项目
  • Transformer - Multi-Head Attention(多头注意力)
  • 网站建设及安全管理花店网站模板
  • A股大盘数据-20250924分析
  • 双目深度相机--10.双目视觉的主要步骤讲解分析
  • 【双光相机配准】可见光与红外相机计算Homography
  • 建网站 几个链接PHP网站建设项目经验
  • 石家庄哪里能做门户网站的招商局网站建设方案
  • 南通网站关键词优化广铁建设集团门户网站
  • Code-First 与数据库迁移工具设计文档
  • VScode(Visual Studio Code)常用配置大全(持续更新)
  • 基于Cesium的地图采集点位经纬度工具
  • zookeeper+kafka
  • 慈溪市规划建设网站郑州手工外发加工网
  • HarmonyOS 5 手势系统与高级交互动效开发实战
  • 怎么网站建设到百度wordpress自带ajax很慢
  • 手机微网站怎么设计方案网站建设 分析
  • 【Redis原理】缓存的内部逻辑
  • Java中的大数据流式计算与Apache Kafka集成!
  • 福建省城乡和建设厅网站专业型网站和个人网站
  • 盐城专业做网站的公司哪家好做网站可以没有框架吗
  • HarmonyOS 5 Native与ArkTS混合开发实战:跨语言高性能组件开发
  • 4.11 球谐光照