Golang通脉之流程控制详情
作者:羌 发布时间:2024-02-20 06:56:34
前言:
流程控制是每种编程语言控制逻辑走向和执行次序的重要部分,流程控制可以说是一门语言的“经脉”。
Go语言中最常用的流程控制有if
和for
,而switch
和goto
主要是为了简化代码、降低重复代码而生的结构,属于扩展类的流程控制。
1、if else(分支结构)
1.1 if条件判断基本写法
Go语言中if条件判断的格式如下:
if 表达式1 {
分支1
} else if 表达式2 {
分支2
} else{
分支3
}
当表达式1的结果为true
时,执行分支1,否则判断表达式2,如果满足则执行分支2,都不满足时,则执行分支3。 if判断中的else if
和else
都是可选的,可以根据实际需要进行选择。
关于 if 条件语句的使用有一些规则:
if 后面的条件表达式不需要使用 (),这和有些编程语言不一样,也更体现 Go 语言的简洁;
每个条件分支(
if
或者else
)中的大括号是必须的,哪怕大括号里只有一行代码(如示例);if 紧跟的大括号 { 不能独占一行,
else
前的大括号 } 也不能独占一行,否则会编译不通过;在
if……else
条件语句中还可以增加多个else if
,增加更多的条件分支。
1.2 if条件判断特殊写法
if条件判断还有一种特殊的写法,可以在 if
表达式之前添加一个执行语句,再根据变量值进行判断:
func main() {
if i:=6; i >10 {
fmt.Println("i>10")
} else if i>5 && i<=10 {
fmt.Println("5<i<=10")
} else {
fmt.Println("i<=5")
}
}
2、for(循环结构)
Go 语言中的所有循环类型均可以使用for关键字来完成。
for循环的基本格式如下:
for 初始语句;条件表达式;更新语句{
循环体语句
}
条件表达式返回true
时循环体不停地进行循环,直到条件表达式返回false
时自动退出循环。
func forDemo() {
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
for
循环的初始语句可以被忽略,但是初始语句后的分号必须要写,例如:
func forDemo2() {
i := 0
for ; i < 10; i++ {
fmt.Println(i)
}
}
for循环的初始语句和结束语句都可以省略,例如:
func forDemo3() {
i := 0
for i < 10 {
fmt.Println(i)
i++
}
}
这种写法类似于其他编程语言中的while
,在while
后添加一个条件表达式,满足条件表达式时持续循环,否则结束循环。
2.1 无限循环
for {
循环体语句
}
for
循环可以通过break
、goto
、return
、panic
语句强制退出循环。
在 Go
语言中,同样支持使用 continue
、break
控制 for
循环:
continue
可以跳出本次循环,继续执行下一个循环。
break
可以跳出整个 for 循环
,哪怕 for 循环没有执行完,也会强制终止。
3、for range(键值循环)
Go语言中可以使用for range
遍历数组、切片、字符串、map
及通道(channel
)。
通过for range
遍历的返回值有以下规律:
数组、切片、字符串返回索引和值。
map
返回键和值。通道(
channel
)只返回通道内的值。
注意:
与 for 不同的是,range 对每个迭代值都创建了一个拷贝。因此如果每次迭代的值内存占用很小的情况下,for 和 range 的性能几乎没有差异,但是如果每个迭代值内存占用很大,这种情况下差距就非常明显了。
简单的例子证明 range 迭代时,返回的是拷贝。
persons := []struct{ no int }{{no: 1}, {no: 2}, {no: 3}}
for _, s := range persons {
s.no += 10
}
for i := 0; i < len(persons); i++ {
persons[i].no += 100
}
fmt.Println(persons) // [{101} {102} {103}]
persons
是一个长度为 3 的切片,每个元素是一个结构体。使用
range
迭代时,试图将每个结构体的 no 字段增加 10,但修改无效,因为range
返回的是拷贝。使用 for 迭代时,将每个结构体的 no 字段增加 100,修改有效
range
在迭代过程中返回的是迭代值的拷贝,如果每次迭代的元素的内存占用很低,那么 for 和 range
的性能几乎是一样,例如 []int。但是如果迭代的元素内存占用较高,例如一个包含很多属性的 struct
结构体,那么 for
的性能将显著地高于range
,有时候甚至会有上千倍的性能差异。对于这种场景,建议使用 for,如果使用 range
,建议只迭代下标,通过下标访问迭代值,这种使用方式和 for 就没有区别了。如果想使用 range
同时迭代下标和值,则需要将切片/数组的元素改为指针,才能不影响性能。
4、switch case
使用switch
语句可方便地对大量的值进行条件判断。
func switchDemo1() {
finger := 3
switch finger {
case 1:
fmt.Println("大拇指")
case 2:
fmt.Println("食指")
case 3:
fmt.Println("中指")
case 4:
fmt.Println("无名指")
case 5:
fmt.Println("小拇指")
default:
fmt.Println("无效的输入!")
}
}
Go语言规定每个switch
只能有一个default
分支。
一个分支可以有多个值,多个case
值中间使用英文逗号分隔。
func testSwitch3() {
switch n := 7; n {
case 1, 3, 5, 7, 9:
fmt.Println("奇数")
case 2, 4, 6, 8:
fmt.Println("偶数")
default:
fmt.Println(n)
}
}
分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量:
func switchDemo4() {
age := 30
switch {
case age < 25:
fmt.Println("好好学习吧")
case age > 25 && age < 35:
fmt.Println("好好工作吧")
case age > 60:
fmt.Println("好好享受吧")
default:
fmt.Println("活着真好")
}
}
在 Go 语言中,switch
的 case
从上到下逐一进行判断,一旦满足条件,立即执行对应的分支并返回,其余分支不再做判断。也就是说 Go 语言的 switch 在默认情况下,case 最后自带 break。这和其他编程语言不一样,比如 C 语言在 case 分支里必须要有明确的 break
才能退出一个 case。Go 语言的这种设计就是为了防止忘记写 break
时,下一个 case
被执行。
fallthrough
语法可以执行满足条件的case的下一个case,是为了兼容C语言中的case
设计的。
func switchDemo5() {
s := "a"
switch {
case s == "a":
fmt.Println("a")
fallthrough
case s == "b":
fmt.Println("b")
case s == "c":
fmt.Println("c")
default:
fmt.Println("...")
}
}
输出:
a
b
5、goto(跳转到指定标签)
goto
语句通过标签进行代码间的无条件跳转。goto语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用goto
语句能简化一些代码的实现过程。
例如双层嵌套的for循环要退出时:
func gotoDemo1() {
var breakFlag bool
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
// 设置退出标签
breakFlag = true
break
}
fmt.Printf("%v-%v\n", i, j)
}
// 外层for循环判断
if breakFlag {
break
}
}
}
使用goto语句能简化代码:
func gotoDemo2() {
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
// 设置退出标签
goto breakTag
}
fmt.Printf("%v-%v\n", i, j)
}
}
return
// 标签
breakTag:
fmt.Println("结束for循环")
}
6、break(跳出循环)
break
语句可以结束for
、switch
和select
的代码块。
break
语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的for
、switch
和 select
的代码块上。 举个例子:
func breakDemo1() {
BREAKDEMO1:
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
break BREAKDEMO1
}
fmt.Printf("%v-%v\n", i, j)
}
}
fmt.Println("...")
}
7、continue(继续下次循环)
continue
语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for循环内使用。
在 continue
语句后添加标签时,表示开始标签对应的循环。例如:
func continueDemo() {
forloop1:
for i := 0; i < 5; i++ {
// forloop2:
for j := 0; j < 5; j++ {
if i == 2 && j == 2 {
continue forloop1
}
fmt.Printf("%v-%v\n", i, j)
}
}
}
来源:https://www.cnblogs.com/drunkery/p/15405594.html
猜你喜欢
- 给每一个onClick再附加一个事件 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HT
- 简介A的独有+AB的公有B的独有+AB的公有AB的公有A的独有B的独有A的独有+B的独有+AB的公有A的独有+B的独有练习建表部门表DROP
- 问题描述:被搜索名字为:andy这时搜索andy正常,但是搜索a就搜不到。解决办法,在索引配置文件中的index中添加min_infix_l
- 引言“ 这是MySQL系列笔记的第十二篇,文章内容均为本人通过实践及查阅资料相关整理所得,可用作新手入门指南,
- 首先看官网的DataFrame.plot( )函数DataFrame.plot(x=None, y=None, kind='line
- 导语前几天,有人私信小编:说陪女朋友在小广场上面逛街玩儿扎气球:结果一个都没扎破,扎心了老铁。女朋友都要离家出走了~让我给想想办法:小编只想
- 在程序的开发过程中,处理分页是大家接触比较频繁的事件,因为现在软件基本上都是与数据库进行挂钩的。但效率又是我们所追求的,如果是像原来那样把所
- TensorFlow中tf.batch_matmul()用法如果有两个三阶张量,size分别为a.shape = [100, 3, 4]b.
- 乐观锁乐观锁大多是基于数据版本记录机制实现,一般是给数据库表增加一个"version"字段。读取数据时,将此版本号一同读
- 一、不要使用可变对象作为函数默认值In [1]: def append_to_list(value, def_list=[]):
- 正在看的ORACLE教程是:Oracle 数据表分区的策略。本文描述通过统计分析出医院信息系统需分区的表,对需分区的表选择分区键,即找出包括
- fileinput模块提供处理一个或多个文本文件的功能,可以通过使用for循环来读取一个或多个文本文件的所有行。它的工作方式和readlin
- APScheduler 简介在实际开发中我们经常会碰上一些重复性或周期性的任务,比如像每天定时爬取某个网站的数据、一定周期定时运行代码训练模
- 1 概述利用Python生成简单的词云,需要的工具是cython,wordcloud与anaconda.2 准备工作包括安装cython,w
- 本文实例讲述了Python自然语言处理 NLTK 库用法。分享给大家供大家参考,具体如下:在这篇文章中,我们将基于 Python 讨论自然语
- scikit-learn 是基于 Python 语言的机器学习工具简单高效的数据挖掘和数据分析工具可供大家在各种环境中重复使用建立在 Num
- 1. 新建项目在命令行窗口下输入scrapy startproject scrapytest, 如下然后就自动创建了相应的文件,如下2. 修
- 在前面的文章 Python 计算机视觉(十五)—— 图像特效处理 中我已经介绍了大部分的图像的特效处理,但还是忽略了油画特效的处理,在本篇文
- 今天遇到一个问题,原有生产系统正在健康运行,现需要监控一张数据表,当增加数据的时候,给管理员发送邮件。领到这个需求后,有同事提供方案:写触发
- 使用MySQL,安全问题不能不注意。以下是MySQL提示的23个注意事项:1。如果客户端和服务器端的连接需要跨越并通过不可信任的网络,那么就