流程结构就是指程序逻辑到底怎么执行,进而言之,程序执行逻辑的顺序。众所周知,程序整体都是自上由下执行的,但有的时候,又不仅仅是从上往下执行那么简单,大体上,Go lang程序的流程控制结构一共有三种:顺序结构,选择结构,循环结构。顺序结构:从上向下,逐行执行;选择结构:条件满足,某些代码才会执行,0-1次;循环结构:条件满足,某些代码会被反复的执行多次,0-N次

选择结构之条件判断if/else

市面上的语言都有if/else逻辑,逻辑非常简单,只要满足条件,就会执行条件代码块的逻辑:

if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
} if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
} else {
/* 在布尔表达式为 false 时执行 */
} if 布尔表达式1 {
/* 在布尔表达式1为 true 时执行 */
} else if 布尔表达式2{
/* 在布尔表达式1为 false ,布尔表达式2为true时执行 */
} else{
/* 在上面两个布尔表达式都为false时,执行*/
}

具体逻辑:

package main  

import "fmt"  

func main() {  

	var a int = 1  

	/* 使用 if 语句判断布尔表达式 */
if a < 20 {
/* 如果条件为 true 则执行以下语句 */
fmt.Printf("a 小于 20\n")
}
fmt.Printf("a 的值为 : %d\n", a)
}

程序返回:

a 小于 20
a 的值为 : 1

需要注意的是,条件变量类型要一致才能比较。

除此之外,if还可以在判断之前执行逻辑:

package main  

import (
"fmt"
) func main() {
if num := 10; num%2 == 0 { //checks if number is even
fmt.Println(num, "is even")
} else {
fmt.Println(num, "is odd")
}
}

程序返回:

10 is even

也就是说,当判断变量num对2取余是否等于0之前,我们可以先给num进行赋值操作。

同时if/else也支持多分支判断:



package main  

import (
"fmt"
) func main() {
score := 88
if score >= 90 {
fmt.Println("成绩等级为A")
} else if score >= 80 {
fmt.Println("成绩等级为B")
} else if score >= 70 {
fmt.Println("成绩等级为C")
} else if score >= 60 {
fmt.Println("成绩等级为D")
} else {
fmt.Println("成绩等级为E 成绩不及格")
}
}

程序返回:

成绩等级为B

这里程序根据变量的值而选择执行不同的分支代码,但需要注意的是,Go lang对于 { 和 } 的位置有严格的要求,它要求 else if (或 else ) 和两边的花括号,必须在同一行。即使在 { 和 } 之间只有一条语句,这两个花括号也是不能省略的。

选择结构之选择判断switch

switch关键字是一个条件语句,它计算表达式并将其与可能匹配的列表进行比较,并根据匹配执行代码块。它可以被理解为用一种普适的方式来写多个if else判断子句。

switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上直下逐一测试,直到匹配为止。 switch 语句执行的过程从上至下,直到找到匹配项,匹配项后面也不需要再加break。

说白了就是,每一个case都默认自动break,执行完了一个,switch逻辑也就结束了,不会顺序执行别的case,但是可以使用fallthrough强制执行后面的case代码:



package main  

import "fmt"  

func main() {
/* 定义局部变量 */
var grade string = "B"
var marks int = 40 switch marks {
case 90:
grade = "A"
case 80:
grade = "B"
case 50, 60, 70:
grade = "C" //case 后可以由多个数值
default:
grade = "D"
} switch {
case grade == "A":
fmt.Printf("A\n")
case grade == "B", grade == "C":
fmt.Printf("B\n")
case grade == "D":
fmt.Printf("D\n")
case grade == "F":
fmt.Printf("F\n")
default:
fmt.Printf("low\n")
}
fmt.Printf("你的等级是 %s\n", grade)
}

程序返回:

D
你的等级是 D

这里我们先通过switch对marks变量进行值判断,在case分支里赋值grade变量,随后又在switch逻辑中对grade做恒等判断,然后输出。

假设需要贯通后续的case,就添加fallthrough关键字:

package main  

import (
"fmt"
) func main() {
switch x := 5; x {
default:
fmt.Println(x)
case 5:
x += 10
fmt.Println(x)
fallthrough
case 6:
x += 20
fmt.Println(x) } }

这里首先进入case5逻辑,x经过运算后变为15,随后贯通进入下一个逻辑,x += 20 逻辑,变为35。

程序返回:

15
35

需要注意的是,fallthrough应该是某个case的最后一行。如果它出现在中间的某个地方,编译器就会抛出错误。

循环结构之遍历for

for关键字可以用来重复执行某一段代码,在Python中,遍历方式有三种:for 、 while 和 do while 。但是Go lang只为我们提供了一种:for:

package main  

import (
"fmt"
) func main() {
num := 1
for num < 3 {
fmt.Println(num)
num++
} }

程序返回:

1
2

这里是但条件循环,如果满足条件,for代码块的逻辑会重置执行。

我们还可以为遍历添加额外的表达式逻辑,比如初始化控制变量,在整个循环生命周期内,只执行一次;设置循环控制条件,该表达式值为 true 时循环,值为 false 时结束循环;每次循环完都会执行此表达式,可以利用其让控制变量增量或减量:

package main  

import (
"fmt"
) func main() {
for num := 0; num < 4; num++ {
fmt.Println(num)
} }

程序返回:

0
1
2
3

需要注意的是,在for关键字中声明的变量,也只在for的代码块中有效,因为和Python不同,go lang有严格的块作用域限制。

在 Go lang中遍历一个可迭代的对象一般使用 for-range 语句实现,其中 range 后面可以接数组、切片、字符串等, range 会返回两个值,第一个是索引值,第二个是数据值:

package main  

import (
"fmt"
) func main() { str := "123456789"
for index, value := range str {
fmt.Printf("index %d, value %c\n", index, value)
} }

程序返回:

index 0, value 1
index 1, value 2
index 2, value 3
index 3, value 4
index 4, value 5
index 5, value 6
index 6, value 7
index 7, value 8
index 8, value 9

如果for关键字后面没有表单式,就是死循环:

package main  

import (
"fmt"
) func main() { num := 1 for { fmt.Println(num)
num++ if num > 3 {
break
} } }

程序返回:

1
2
3

是的,我们当然可以使用break关键字来中断循环。

但需要注意的是,break只能终端当前循环,不能终端外部循环:

package main  

import "fmt"  

func main() {
/* 定义局部变量 */
var i, j int
for i = 2; i < 10; i++ {
for j = 2; j <= (i / j); j++ {
if i%j == 0 {
break // 如果发现因子,则不是素数
}
}
if j > (i / j) {
fmt.Printf("%d 是素数\n", i)
}
}
}

程序返回:

2  是素数
3 是素数
5 是素数
7 是素数

和Python一样,Go lang也具备continue关键字,continue 语句用来跳出 for 循环中的当前循环:

package main  

import "fmt"  

func main() {  

	for num := 1; num <= 10; num++ {
if num%2 == 0 {
continue
}
fmt.Println(num)
} }

程序返回:

1
3
5
7
9

在 continue 语句后的所有的 for 循环语句都不会在本次循环中执行,执行完 continue 语句后将会继续执行一下次循环。这样我们就可以跳过偶数,直接打印出 10 以内的奇数。

goto 无条件跳转

使用goto关键字可以直接跳到下一步要执行的标签代码:

package main  

import "fmt"  

func main() {  

	for x := 0; x < 10; x++ {  

		for y := 0; y < 10; y++ {  

			if y == 2 {
// 跳转到标签
goto breakHere
} }
} // 手动返回, 避免执行进入标签
return // 标签
breakHere:
fmt.Println("done")
}

程序返回:

done

需要注意的是,goto关键字与标签之间不能有变量声明,否则编译错误。

结语

和Python和Ruby相比,整体上,在流程结构控制环节,Go lang表现出了极大的克制,语法上删繁就简, 把动态语言那些桀骜不驯的语法糖压制成行文工整的诗,这样的好处是对初学者极为友好,没有太多规范需要记忆,大道至简,大巧不工。我们可以吐槽它没有while或者是do while,亦或者是lambda表达式等可以炫技的资本,但,那又如何呢?就像乔帮主在聚贤庄力战群雄,大杀四方,所倚重的不过是一套普普通通的太祖长拳,Go lang亦如此,务实胜过炫技,简单未必普通。

巨细靡遗流程控制,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang流程结构详解EP09的更多相关文章

  1. 延宕执行,妙用无穷,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中defer关键字延迟调用机制使用EP17

    先行定义,延后执行.不得不佩服Go lang设计者天才的设计,事实上,defer关键字就相当于Python中的try{ ...}except{ ...}finally{...}结构设计中的finall ...

  2. 仙人指路,引而不发,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中New和Make函数的使用背景和区别EP16

    Golang只有二十五个系统保留关键字,二十几个系统内置函数,加起来只有五十个左右需要记住的关键字,纵观编程宇宙,无人能出其右.其中还有一些保留关键字属于"锦上添花",什么叫锦上添 ...

  3. 清源正本,鉴往知来,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中引用类型是否进行引用传递EP18

    开篇明义,Go lang中从来就不存在所谓的"引用传递",从来就只有一种变量传递方式,那就是值传递.因为引用传递的前提是存在"引用变量",但是Go lang中从 ...

  4. 你有对象类,我有结构体,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang结构体(struct)的使用EP06

    再续前文,在面向对象层面,Python做到了超神:万物皆为对象,而Ruby,则干脆就是神:飞花摘叶皆可对象.二者都提供对象类操作以及继承的方式为面向对象张目,但Go lang显然有一些特立独行,因为它 ...

  5. 百亿数据百亿花, 库若恒河沙复沙,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang数据库操作实践EP12

    Golang可以通过Gorm包来操作数据库,所谓ORM,即Object Relational Mapping(数据关系映射),说白了就是通过模式化的语法来操作数据库的行对象或者表对象,对比相对灵活繁复 ...

  6. 层次分明井然有条,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang包管理机制(package)EP10

    Go lang使用包(package)这种概念元素来统筹代码,所有代码功能上的可调用性都定义在包这个级别,如果我们需要调用依赖,那就"导包"就行了,无论是内部的还是外部的,使用im ...

  7. 兔起鹘落全端涵盖,Go lang1.18入门精炼教程,由白丁入鸿儒,全平台(Sublime 4)Go lang开发环境搭建EP00

    Go lang,为并发而生的静态语言,源于C语言又不拘泥于性能,高效却不流于古板,Python灵活,略输性能,Java严谨,稍逊风骚.君不见各大厂牌均纷纷使用Go lang对自己的高并发业务进行重构, ...

  8. 化整为零优化重用,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang函数的定义和使用EP07

    函数是基于功能或者逻辑进行聚合的可复用的代码块.将一些复杂的.冗长的代码抽离封装成多个代码片段,即函数,有助于提高代码逻辑的可读性和可维护性.不同于Python,由于 Go lang是编译型语言,编译 ...

  9. 因势而变,因时而动,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang泛型(generic)的使用EP15

    事实上,泛型才是Go lang1.18最具特色的所在,但为什么我们一定要拖到后面才去探讨泛型?类比的话,我们可以想象一下给小学一年级的学生讲王勃的千古名篇<滕王阁序>,小学生有多大的概率可 ...

随机推荐

  1. ArrayList常用Api分析及注意事项

    数组(定长,有序的,随机访问).ArrayList是Java在数组的基础上进行衍生出来的Java里的一种数据结构,它在拥有数据的特性之外,增加了可变性 (动态数组). 属性 属性 备注 DEFAULT ...

  2. chkconfig-配置系统服务

    管理Linux系统开机启动项. chkconfig命令默认在CentOS7+中不被使用了,由于系统服务管理都交给了systemctl托管. 语法 chkconfig [--list] [--type ...

  3. 《Effective C++》阅读总结(三):资源管理

    C++中的资源管理非常重要,在将资源加载到内存后,便可以使用资源了,当我们不再需要资源时,我们要保证其正确的释放,才能将其占用的内存空间归还给操作系统,不正确的释放很容易造成内存泄漏.本章以资源管理类 ...

  4. 聊聊OOP中的设计原则以及访问者模式

    一  设计原则 (SOLID) 1.  S - 单一职责原则(Single Responsibllity Principle) 1.1  定义 一个类或者模块只负责完成一个职责(或功能), 认为&qu ...

  5. 「洛谷 P3834」「模板」可持久化线段树 题解报告

    题目描述 给定n个整数构成的序列,将对于指定的闭区间查询其区间内的第k小值. 输入输出格式 输入格式 第一行包含两个正整数n,m,分别表示序列的长度和查询的个数. 第二行包含n个整数,表示这个序列各项 ...

  6. Java - 六原则一法则

    Java - 六原则一法则 单一职责原则:一个类只做它该做的事情.(单一职责原则想表达的就是"高内聚",写代码最终极的原则只有六个字"高内聚.低耦合",所谓的高 ...

  7. Arraylist集合、对象数组

    Arraylist集合 ArrayList是List接口的一个实现类,它是程序中最常见的一种集合. 他的特点:在增加或删除指定位置的元素时,会创建新的数组,效率比较低,因此不适合做大量的增删操作,Ar ...

  8. 跟着Vam一起学习Typescript(第一期)

    一.安装环境与配置1.命令行安装 npm i -g typescript 2.快捷打开Vs Code编辑器 创建一个项目文件夹,在该文件夹下打开命令行工具,使用code .命令快速打开编辑器(如果计算 ...

  9. 第一章:Python的数据结构、函数和文件

    list list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出班里所有同学的名字,就可以用一个list表示: >>> classmates = ['Michael', ...

  10. Windows 2008R2 IIS环境配置(靶机)

    一.Windows 2008 R2系统安装 VMware Workstation 15安装包 链接:https://pan.baidu.com/s/11sYcZTYPqIV-pyvzo7pWLQ 提取 ...