Go_流程、跳转控制语详解

流程控制语句分类:

流程控制语句可以控制代码的执行顺序和条件

  1. 顺序结构:普通的代码,由上而下依次执行
  2. 分支结构(if, switch)
  3. 循环结构(for)

if语句:

条件表达式值必须是bool类型,不可省略括号,且左大括号不能另起一行

格式1:

if (关系表达式) {语句体;	
}

执行流程:

  1. 首先计算关系表达式的值
  2. 如果关系表达式的值为true就执行语句体
  3. 如果关系表达式的值为false就不执行语句体
  4. 继续执行后面的语句内容

if语句格式2

if (关系表达式) {语句体1;	
} else {语句体2;	
}

执行流程:

  1. 首先计算关系表达式的值
  2. 如果关系表达式的值为true就执行语句体1
  3. 如果关系表达式的值为false就执行语句体2
  4. 继续执行后面的语句内容

if语句格式3

if (关系表达式1) {语句体1;	
} else if (关系表达式2) {语句体2;	
}else {语句体n+1;
}
  1. 首先计算关系表达式1的值
  2. 如果值为true就执行语句体1;如果值为false就计算关系表达式2的值
  3. 如果值为true就执行语句体2;如果值为false就计算关系表达式3的值
  4. 如果没有任何关系表达式为true,就执行语句体n+1。

演示:

定义一个在0~100之间的变量a, 判断分数在什么范围,90 ~ 100优秀,80 ~ 89良好,70 ~ 79中等,60 ~ 69及格,0 ~ 59请努力加油!

func main() {// 定义一个在0~100之间的变量a, 判断分数在什么范围,90 ~ 100优秀,80 ~ 89良好,70 ~ 79中等,60 ~ 69及格,0 ~ 59请努力加油!var a float64fmt.Println("请输入成绩:")fmt.Scan(&a)if a >= 90 && a <= 100 {fmt.Println("优秀")} else if a >= 80 && a <= 89 {fmt.Println("良好")} else if a >= 70 && a <= 79 {fmt.Println("中等")} else if a >= 60 && a <= 69 {fmt.Println("及格")} else if a >= 0 && a <= 59 {fmt.Println("有脸吃饭?")} else {fmt.Println("成绩需在0~100之间")}
}

死代码:指永远不会被执行的代码,数据被定义成常量时就容易产生死代码

func main() {x := 8if x > 5 { 			//优先判断,条件表达式结果为true。println("a")} else if x > 7 { 	// 永远不会执行println("b")}
}

在if中可以定义局部变量赋值后再做条件判断,可以调用函数时传参再判断

func main() {if age := 18; age <= 18 {fmt.Println()}age // 只能在if中使用
}

switch语句:

  • switch和case后面是一个表达式,也可以是常量、变量、有返回值的函数,switch后面也可以不带表达式,无表达式时为true
  • case常量值不能重复,case后的表达式可以有多个,使用逗号间隔
  • Go语言中的switch默认给每个case自带break,因此匹配成功后不会向下执行其他的 case 分支,而是跳出整个switch
  • 如需要穿透后续的case须使用fallthrough强制执行下一个的case代码,switch只能穿透一个case,fallthrough必须放在case分支的最后一行,否则编译报错。
  • 如果所有的case都和表达式的值不匹配,就会执行default语句体部分,default不是必须要写的

格式:

 switch (表达式) {case 1:语句体1case 2:语句体2...default:语句体}

执行流程:

  • 首先计算出表达式的值
  • 其次,和case依次比较,一旦有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结束。
  • 最后,如果所有的case都和表达式的值不匹配,就会执行default语句体部分,然后程序结束掉。 所以建议将default放在末尾

定义一个在0~100之间的变量a,判断分数在什么范围,90 ~ 100优秀,80 ~ 89良好,70 ~ 79中等,60 ~ 69及格,0 ~ 59请努力加油!

func main() {var score float64fmt.Println("请输入成绩:")_, err := fmt.Scan(&score)if err != nil {return }switch {case score >= 90 && score <= 100:fmt.Println("优秀")case score >= 80 && score <= 89:fmt.Println("良好")case score >= 70 && score <= 79:fmt.Println("中等")case score >= 60 && score <= 69:fmt.Println("及格")case score >= 0 && score <= 59:fmt.Println("有脸吃饭?")default:fmt.Println("成绩必须在0~100之间")}
}

case表达式值的数据类型必须和switch的数据类型一致

func main() {var num1 int = 1var num2 int64 = 1var num3 float64 = 1switch num1 {case num2: // 报错:'num1' (类型 'int64' 和 'int' 不匹配) 的 switch 中的 case 'num2' 无效fmt.Println(num2)case num3: // 报错:'num1' (类型 'int64' 和 'int' 不匹配) 的 switch 中的 case 'num2' 无效fmt.Println(num2)default:fmt.Println("error")}
}

case的后面可以有多个表达式,使用逗号间隔即可,但case的表达式后面如果跟的是常量值,则要求不能重复

func main() {var num1 int = 1var num2 int = 1switch num1 {case num2, 2, 3:fmt.Println("没问题")case 3: // 报错:case 3的值重复,常量值不能重复fmt.Println("有问题")case num1 + num2: // 这里的结果也是2,但是不是常量值,所以不会报错fmt.Println("没问题")}
}

fallthrough必须放在case块结尾

func main() {var num int = 10switch num {case 10:fmt.Println("case 10 匹配成功")fallthrough // 默认只能穿透一层case 20:fmt.Println("只能穿透到这里")case 30:fmt.Println("case 30 匹配成功")default:fmt.Println("default")}
}

输出:

case 10 匹配成功
只能穿透到这里

fallthrough如果放在default的前面,则会穿透default

func main() {var num int = 30switch num {case 10:fmt.Println("case 10 匹配成功")case 20:fmt.Println("case 20 匹配成功")case 30:fmt.Println("case 30 匹配成功")fallthrough // 默认只能穿透一层default:fmt.Println("default")}
}

输出:

case 30 匹配成功
default

如果fallthrough前面手动执行break就会中断fallthrough执行

func main() {var num int = 50switch num {default:fmt.Println("default在fallthrough前,则不会执行default")case 10:fmt.Println("case 10 匹配成功")case 20:fmt.Println("case 20 匹配成功")break   // 如果执行fallthrough前手动break就会中断fallthrough执行fallthrough // 默认只能穿透一层case 30:fmt.Println("走到这里说明被穿透了")}
}

switch还被用来替换if语句,被省略的switch条件表达式默认值为true,继而与case比较表达式结果匹配

func main() {switch x := 5; { // 相当于定义了变量x=5,"switch x := 5; true { ... } ,但是一定要加分号,否则报错case x > 5:fmt.Println("x > 5")case x > 0 && x <= 5: // 多条件是 OR 关系,不能写成“case x > 0, x <= 5”。fmt.Println("x > 0 && x <= 5")default:fmt.Println("default")}
}

fallthrough也可以用来判断接口变量的类型,根据类型再做数据处理。但是如果使用fallthrough,那么其中的case就不能再使用fallthrough

func main() {var x interface{} // 定义空接口var y int64 = 10x = y // 把y赋值给x,此时x的数据类型为int64switch i := x.(type) {case int:fmt.Println("x的值是int", i)case int32:fmt.Println("x的值是int32")case int64:fmt.Println("x的值是int64")case float32:fmt.Println("x的值是float32")//fallthrough    不能使用case float64:fmt.Println("x的值是float64")}
}

for循环

循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将一直执行下去,形成死循环。

range和fori循环中的局部变量都会被重复使用

格式

for (初始化语句;条件判断语句;条件控制语句) {循环体语句;
}// 三种for定义格式:func main() {// 格式1for i := 0; i < 3; i++ {}//初始化表达式支持函数调用或定义局部变量。x := 3for x < 10 { // 循环外定义初始化x++}for { 		// 死循环,相当于"while true {}” 或 “for true {}”。循环体语句}for ; ; {} // 死循环,只不过格式不同
}

格式解释:

  • 初始化语句: 用于表示循环开启时的起始状态,就是循环开始的时候什么样
  • 条件判断语句:用于表示循环反复执行的条件,就是判断循环是否能一直执行下去
  • 循环体语句: 用于表示循环反复执行的内容,就是循环反复执行的事情
  • 条件控制语句:用于表示循环执行中每次变化的内容,就是控制循环是否能执行下去

执行流程

  1. 执行初始化语句
  2. 执行条件判断语句,看其结果是true还是false
    如果是false,循环结束
    如果是true,继续执行
  3. 执行循环体语句
  4. 执行条件控制语句
  5. 回到2继续

求1-100之间的偶数和,并把求和结果在控制台输出

func main() {var sum intfor i := 0; i <= 100; i++ {if i%2 == 0 {sum += i}}fmt.Println(sum)
}// 每次直接加2,不需要if判断
func main() {var sum intfor i := 2; i <= 100; i += 2 {sum += i}fmt.Println(sum)
}

可以遍历字符串和数组

func main() {var name string = "itzhuzhu"for i := 0; i < len(name); i++ {fmt.Printf("%c\n", name[i])}
}

如果遍历的字符串内含有中文会报错,因为遍历是按照字节来的,一个中文占用3个字节,需要转成切片再遍历,或者使用range遍历,range是按照字符遍历的

func main() {var name string = "itzhuzhu我乱码了吗"str := []rune(name)for i := 0; i < len(str); i++ {fmt.Printf("%c\n", str[i])}
}

range方式遍历

func main() {var name string = "haha我乱码了吗"for i, v := range name {fmt.Printf("索引:%d,数据:%c", i, v)}
}

range

  • range本质是一个函数,在使用的时候可以加括号使用
  • 修改range得到的value不影响原切片/数组的数据,value就是个副本,和原数据无关,但是在range循环里打印的话还是副本的内容
  • range和fori循环中的局部变量都会被重复使用

range 关键字用于

  • for循环中迭代数组、切片、channel、map的元素
  • 在数组和切片中它返回元素的索引值
  • 在集合中返回 key-value 对的 key 值

格式:

  // for 索引,值 := range 循环数据 for index,value := range arr {}

通过参数列表传递多个参数,使用range获取数据

func main() {//Demo01(1, 2, 3, 4, 5)//Demo02(1, 2, 3, 4, 5)Demo03(1, 2, 3, 4, 5)
}// a代表索引    v代表数据func Demo01(num ...int) {for a, v := range num {fmt.Print("a = ", a, "    ")fmt.Println("v = ", v)}
}// 如果只写一个变量,取出的是索引func Demo02(num ...int) {for v := range num {//fmt.Print("a = ", a, "    ")fmt.Println("v = ", v)}
}// 可以把a使用_代替,表示是一个匿名变量,匿名变量不会保存具体的数据,就可以用v取出数据func Demo03(num ...int) {for _, v := range num {//fmt.Print("a = ", a, "    ")fmt.Println("v = ", v)}
}

演示:

type Student struct {name stringage  int
}func main() {s := Student{"韩信", 10}s2 := Student{"娜可露露", 20}s3 := []Student{s, s2}arr := [3]int{1, 2, 3}// range是一个函数,也可以写成 for i, v := range (arr) {// 将arr遍历然后返回给v,所以在range内修改arr的值,不会影响原数据for i, v := range arr {arr[0] = 10fmt.Println("range", i, v)}// 同样的修改v的值也不会影响原数据for _, v := range s3 {v.age = 99fmt.Println("range", v.age)}fmt.Println(arr)fmt.Println(s3)
}

无论是普通for循环,还是range迭代,其定义的局部变量都会重复使用

func main() {str := [3]string{"a", "b", "c"}for i, s := range str {println(&i, &s)}
}

输出:

0x14000062ee0 0x14000062ef8
0x14000062ee0 0x14000062ef8
0x14000062ee0 0x14000062ef8

如果range调用函数,函数只会被执行一次

func data() []int {fmt.Println("初始化")return []int{10, 20, 30}
}func main() {for i, x := range data() {fmt.Println(i, x)}
}

输出:

初始化
0 10
1 20
2 30

跳转控制语句break:

  • 跳转控制语句break用在循环语句中跳出当前循环,执行循环后面的语句,可以在switch、for中使用
  • 多重循环时默认跳出最近的循环,在循环嵌套中可以使用关键字label标记要跳出的位置

演示:

func main() {for i := 1; i <= 5; i++ {if i == 3 {break}fmt.Println(i) // 结果是1、2   break会直接跳出for循环}
}

计算100以内的偶数和,当偶数和大于100时停止循环并打印出当前i的值

func main() {sum := 0for i := 0; i < 100; i++ {if i%2 == 0 {sum += iif sum > 100 {fmt.Println("sum>100时,i=", i)break}}}
}

输出:

sum>100时,i= 20

指定跳转:

func main() {lable: // 要跳过的代码前要跳过的代码break lable//要跳过的代码后的位
}

多重循环,内循环为2时结束全部循环

func main() {
label:for i := 0; i < 10; i++ {for j := 0; j < 10; j++ {if j == 2 {break label}fmt.Println(j)}}
}

输出:

0
1

跳转控制语句continue:

  • 跳转控制语句(continue):满足条件后,跳过本次循环,继续下次循环,基于条件控制, 在循环内部使用,for可以用
  • 注意: continue只能在循环中进行使用!
  • 在多重循环中可以使用标号label跳出循环

判断10以内的奇数并打印

func main() {for i := 1; i <= 5; i++ {if i == 2 {continue}fmt.Println(i)  // 结果是1、3、4、5     continue会跳过2,执行后面的}
}

多重循环时判断是否等于2,等于2时跳过当前循环,继续下一次循环

func main() {for i := 0; i < 3; i++ {for j := 0; j < 3; j++ {if j == 2 {continue}fmt.Print(j)}}
}

输出:

010101

跳转控制语句(return):

retur表示终止函数或方法

func main() {// 		return // 放在这里等于是结束函数for i := 1; i <= 5; i++ {if i == 3 {break}fmt.Println("return前")return // 放在这里是结束循环fmt.Println("return后")fmt.Println(i)}
}

输出:

return前

跳转控制语句(goto)`

跳转控制语句(goto):转移到指定的行,goto一般配合条件判断使用,可以用来做条件转移,跳出循环等操作

建议尽量不使用goto,但是Go 语言是支持goto

Go语言的goto语句可以无条件地转移到过程中指定的行。

goto语句通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能。但是,在结构化程序设计中一般不主张使用 goto语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难。

goto格式:

goto label
...
label : statement

演示:

func main() {goto label // 跳过123,执行45fmt.Println(1)fmt.Println(2)fmt.Println(3)
label:fmt.Println(4)fmt.Println(5)
}

如果向后面跳,会死循环

func main() {
label:fmt.Println("走我了吗")goto label
}

不能跳到其他函数或内部代码块

func gotoTest() {test: // 未使用的标签 'test'fmt.Println("gotoTest...")
}func main() {for i := 0; i < 5; i++ {loop: // 未使用的标签 'loop'fmt.Println("goto03...")}goto loop // 未解析的标签 'loop'goto test // 未解析的标签 'test'
}

循环嵌套

循环嵌套也可以说是多重循环,就是在一个循环体里面嵌入另一个循环

打印乘法口诀表案例:

func forDemo6() {for i := 1; i <= 9; i++ { // 外循环控制行for j := 1; j <= i; j++ { // 内循环控制列fmt.Printf("%d*%d=%d ", j, i, j*1)}fmt.Print("\n")}
}

输出结果:

1*1=1 
1*2=1 2*2=2 
1*3=1 2*3=2 3*3=3 
1*4=1 2*4=2 3*4=3 4*4=4 
1*5=1 2*5=2 3*5=3 4*5=4 5*5=5 
1*6=1 2*6=2 3*6=3 4*6=4 5*6=5 6*6=6 
1*7=1 2*7=2 3*7=3 4*7=4 5*7=5 6*7=6 7*7=7 
1*8=1 2*8=2 3*8=3 4*8=4 5*8=5 6*8=6 7*8=7 8*8=8 
1*9=1 2*9=2 3*9=3 4*9=4 5*9=5 6*9=6 7*9=7 8*9=8 9*9=9 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/572123.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDU 4027 Can you answer these queries?(线段树/区间不等更新)

传送门 Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)Total Submission(s): 18290 Accepted Submission(s): 4308 Description A lot of battleships of evil are arranged in a line before the b…

Go_秒懂函数、参数、可变参数、匿名函数、回调函数、内置函数

函数是将具有独立功能的代码块组成一个整体&#xff0c;使其具有特殊功能的代码集。它将复杂的算法过程分解为若干个小任务&#xff0c;隐藏相关细节&#xff0c;使得程序结构更加清晰&#xff0c;易于维护。通过接收输入参数完成一段算法指令&#xff0c;输出或存储相关结果。…

NE2018届校招内推笔试——数据挖掘

【单选题|2分/题】 1、在只有两类的情况下&#xff0c;二维特征向量通过共享相同的协方差矩阵的正态分布生成&#xff0c;其中协方差矩阵为&#xff1a; 均值向量分别为&#xff1a;&#xff0c;则根据贝叶斯分类&#xff0c;样本分类为&#xff1a;&#xff08;&#xff09; A…

Go_数组遍历、最大值、求和、多维数组

数组&#xff1a; 数组就是用来存储数据的容器&#xff0c;存储多个数据时数据类型要一致。如果想要保存任意类型数据&#xff0c;需要声明为接口类型数组数组定义完成后&#xff0c;可以对数组进行赋值操作。数组是通过下标来进行操作的&#xff0c;下标的范围是从0开始到数组…

全局变量和环境变量的区别

全局变量:启动脚本了.在各线程,以及主程序中.可以互相传递值.每次启动脚本,初始值都一样.环境变量:启动脚本了.在各线程,以及主程序中.可以互相传递值.每次启动脚本,初始值是上次停止脚本时的值. 例子:Global 全局变量Dimenv 环境变量全局变量 全局变量 1环境变量 环境变量 …

不满足依赖关系

今晚上脑残&#xff0c;替换了实体&#xff0c;把报错的也都替换完成了&#xff0c;但是运行报错&#xff1a; 大概的意思就是说不满足XXXXXX依赖关系&#xff0c;但是找了半天都没有找到&#xff0c;最后是mapper的实体类全路径替换的时候&#xff0c;脑残在后面加上了.java。…

Go_切片(初始化、遍历、截取、修改、append、copy、切片作为函数参数、切片求和、切片求最大值)

切片&#xff1a; 切片的长度是不固定的&#xff0c;可以追加数据&#xff0c;可以理解是一个动态数组&#xff0c;切片的底层是一个结构体切片类型&#xff08;slice&#xff09;本身并不是动态数组或数组指针。它内部通过指针引用底层数组&#xff0c;设定相关属性将操作限定…

Golang——递归的使用

递归指的是函数定义中调用函数本身的现象&#xff08;自己调自己&#xff09;把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算 递归注意事项&#xff1a; 递归一定要有出口。否则内存溢出(出口…

阿里巴巴Java开发手册——速读记录

本随笔基于阿里巴巴Java开发手册V1.2&#xff0c;陆陆续续记录一些现阶段能理解的&#xff0c;有启发的内容&#xff0c;并将持续更新 最佳实践——插件使用已经发布为随笔&#xff01;http://www.cnblogs.com/jiangbei/p/7668654.html 一、编程规范 1.命名规范 &#xff08;1&…

Go_map集合初始化、键值操作、map作为函数参数的使用

map&#xff1a; map是key-value的数据结构&#xff0c;类似于Java的集合&#xff0c;又称为字典&#xff0c;像新华字典就是key:value类型展示的map是无序的&#xff0c;其中key是不允许重复的&#xff0c;key不存在相当于添加&#xff0c;存在相当于修改map的key必须可以进行…

Angular 小试牛刀[1]:Getting Started

首先&#xff0c;Angular2 与 Angular1.x 版本没有多大关系&#xff0c;甚至可以说是两个完全不一样的框架&#xff0c;故 Angular 指的是 Angular2 及以上的版本。而 Angular 与 TypeScript 的完美结合&#xff0c;对于一个 .NET 开发者来说&#xff0c;实在是找不到不用它的理…

Go_指针的使用、数组指针和指针数组、指针与切片、指针与结构体、多级指针

指针&#xff1a; 指针是一个特殊的变量&#xff0c;因为它存储的数据是另一个变量的内存地址&#xff0c;指针本身也是有内存地址的指针的数据类型有int、float、bool、string、数组、结构体指针的作用就是可以通过变量/对象的内存地址去操作变量/对象 注意&#xff1a; 取址运…

linux驱动编写(Kconfig文件和Makefile文件)

在Linux编写驱动的过程中&#xff0c;有两个文件是我们必须要了解和知晓的。这其中&#xff0c;一个是Kconfig文件&#xff0c;另外一个是Makefile文件。如果大家比较熟悉的话&#xff0c;那么肯定对内核编译需要的.config文件不陌生&#xff0c;在.config文件中&#xff0c;我…

Go_结构体与数组、切片、map、方法、作为函数参数、type、Tag

结构体&#xff1a; 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合结构体可以很好的管理数据&#xff0c;使用结构体可以提高程序的易读性&#xff0c;类似于Java的类一样结构体内成员名必须唯一&#xff0c;可用_补位&#xff0c;支持使用自身类型的指针成员。…

vue项目中如何引入ElementUI

1.在cmd中输入命令&#xff1a; npm i element-ui -S 2.在src/main.js文件中增加代码&#xff1a; import ElementUI from element-ui import element-ui/lib/theme-default/index.cssVue.use(ElementUI) 转载于:https://www.cnblogs.com/xuemei/p/7372332.html

Golang——深浅拷贝

浅拷贝&#xff1a;只是拷贝了内存地址&#xff0c;会指向原来的内存&#xff0c;指向原来的内存地址&#xff0c;操作的时候会互相影响 go中的赋值、函数传参、函数返回值都是浅拷贝 深拷贝&#xff1a;会把变量的数据都拷贝一份&#xff0c;包括地址&#xff0c;新的内存地址…

[Java][web]利用Spring随时随地获得Request和Session

利用Spring随时随地获得Request和Session 一、准备工作&#xff1a; 在web.xml中加入 <listener> <listener-class> org.springframework.web.context.request.RequestContextListener</listener-class> </listener>二、用法&#xff1a;…

Golang实现通讯录小案例

代码&#xff1a; package mainimport "fmt"func main() {for {menu()} }type User struct {userName string/**key&#xff1a;表示电话的类型value&#xff1a;电话号码*/addressPhone map[string]string }// 定义切片 var userList make([]User, 0)func menu() …

MySql5.6版修改用户登录密码

1、使用 mysqladmin 方式: 打开命令提示符界面, 执行命令: mysqladmin -u root -p password 新密码 执行后提示输入旧密码完成密码修改, 当旧密码为空时直接按回车键确认即可。 2、UPDATE user 语句&#xff08;我自己用的就是这个方法&#xff09; 这种方式必须是先用root帐户…

Go_面向对象(抽象、封装、继承)

抽象 抽象是一种编程思维方式&#xff0c;是从多个事物中提取共性 例&#xff1a;产品经理和程序员都有工作的方法&#xff0c;但是工作内容不同&#xff0c;可以把工作抽象出来定义为一个方法&#xff0c;具体细节由调用者补充 银行存取款案例&#xff1a; 账号结构体取款方法…