[GO语言基础] 五.顺序控制语句和条件控制语句(if、else、switch)

举报
eastmount 发表于 2021/08/09 18:32:04 2021/08/09
【摘要】 前文介绍了Golang的运算,包括算术运算、逻辑运算、赋值运算、位运算及编程练习。这篇文章将详细讲解顺序控制语句和条件控制语句。 这系列文章入门部分将参考“尚硅谷”韩顺平老师的视频和书籍《GO高级编程》,详见参考文献,并结合作者多年的编程经验进行学习和丰富,且看且珍惜

作为网络安全初学者,会遇到采用Go语言开发的恶意样本。因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识;另一方面是分享与读者,希望大家一起进步。前文介绍了Golang的运算,包括算术运算、逻辑运算、赋值运算、位运算及编程练习。这篇文章将详细讲解顺序控制语句和条件控制语句。 这系列文章入门部分将参考“尚硅谷”韩顺平老师的视频和书籍《GO高级编程》,详见参考文献,并结合作者多年的编程经验进行学习和丰富,且看且珍惜吧!后续会结合网络安全进行GO语言实战深入,加油~

这些年我学过各种编程语言,从最早的C语言到C++,再到C#、PHP、JAVA,再到IOS开发、Python,到最新的GO语言,学得是真的杂。有时候觉得编程语言恰恰是最简单的,而通过一门编程语言能够解决实际问题或深入底层才是其价值所在,并且当我们学好一门编程语言后,其他编程语言都非常类似,殊途同归,学起来也很迅速。

在这里插入图片描述

源码下载地址:

前文参考:


在程序中,程序运行的流程控制决定程序是如何执行的,也是大家必须要掌握的,主要有三大流程控制语句。这篇文章先介绍前两个流程控制。

  • 顺序控制
  • 分支控制
  • 循环控制

一.顺序控制语句

顺序控制是指程序从上到下逐行地执行,中间没有任何判断和跳转。其流程图如下所示:

在这里插入图片描述

下面举个简单的案例说明。代码中没有判断,程序按照默认的流程执行,即顺序控制。

package main
import "fmt"

func main() {
	//假如还有97天放假 问多少个星期多少天
	var num int = 97
	var week int
	var day int
	week = num / 7
	day = num % 7
	fmt.Printf("%d个星期零%d天 \n", week, day)

	//定义一个变量保存华氏温度 转换成摄氏温度
	//摄氏温度=5/9*(摄氏温度-32)
	var huashi float32 = 134.2
	var sheshi float32
	sheshi = 5.0 / 9 * (huashi - 32)
	fmt.Printf("%v 对应的摄氏温度=%v \n", huashi, sheshi)
}

输出结果如下图所示:

在这里插入图片描述

注意,Golang中定义变量时采用合法的前向引用,比如正确形式:

func main() {
	var num1 int = 10          //声明num1
	var num2 int = num1 + 20   //使用num1
	fmt.Println(num2)
}

错误形式:

func main() {
	var num2 int = num1 + 20   //使用num1
	var num1 int = 10          //声明num1(x)
	fmt.Println(num2)
}

二.条件控制语句

分支控制是让程序有选择执行,包括三种常见形式:

  • 单分支
  • 双分支
  • 多分支

1.单分支控制

基本语法如下:

if 条件表达式 {
	执行代码块
}

说明:当条件表达式为True时,就会执行括号中的代码块。 注意{}是必须有的,即使只写一行代码。对应的流程图如下所示:

在这里插入图片描述

案例分析:编写代码实现输入人的年龄,如果年龄大于18岁,则输出“你的年龄大于18岁”。

package main
import "fmt"

func main() {
	//输入年龄
	var age int
	fmt.Println("请输入年龄:")
	fmt.Scanln(&age)

	//单分支判断
	if age > 18 {
		fmt.Println("你的年龄大于18岁")
	}
}

输出结果如下图所示:

在这里插入图片描述

注意事项:

  • 在golang中支持在if语句直接定义一个变量,如下所示:
if n := 20; n > 5 {
	fmt.Println("定义变量的值数字大于5")
}

2.双分支控制

基本语法如下:

if 条件表达式 {
	执行代码块1
} else {
	执行代码块2
}

说明:当条件表达式为True时,否则执行代码块2。注意{}是必须有的,即使只写一行代码。 对应的流程图如下所示:

在这里插入图片描述

案例分析:编写代码实现输入人的年龄,如果年龄大于18岁,则输出“你的年龄大于18岁”;否则输出“你的年龄小于等于18岁”。

package main
import "fmt"

func main() {
	//输入年龄
	var age int
	fmt.Println("请输入年龄:")
	fmt.Scanln(&age)

	//单分支判断
	if age > 18 {
		fmt.Println("你的年龄大于18岁")
	} else {
		fmt.Println("你的年龄小于等于18岁")
	}
}

输出结果如下图所示:

在这里插入图片描述

注意事项:

  • 条件表达式是age > 18,执行代码块1和执行代码块2
  • 双分支只会执行其中一个分支

条件语句嵌套
案例:对下列代码,若有输出,指出输出结果。

package main
import "fmt"

func main() {
	var x int = 4
	var y int = 1
	
	//双分支嵌套判断
	if (x > 2) {
		if (y > 2) {
			fmt.Println(x + y)
			fmt.Println("执行语句:----a----")
		}
		fmt.Println("执行语句:----b----")
	} else {
		fmt.Println("x is", x, "y is", y)
		fmt.Println("执行语句:----c----")
	}
}

输出结果如下图所示:

在这里插入图片描述

条件判断

  • 声明两个int32型变量并复制,判断两个数之和,如果大于等于50输出
  • 声明两个float64型变量,判断第一个数大于10.0,并且第二个数小于20.0输出两数之和
  • 声明两个int32型变量,判断两者之和是否能被3又能被5整除,输出信息
package main
import "fmt"

func main() {
	//判断两个数之和大于等于50
	var n1 int32 = 10
	var n2 int32 = 50
	if n1 + n2 >= 50 {
		fmt.Println("相加结果大于等于50")
	}

	//判断第一个数大于10.0,并且第二个数小于20.0
	var n3 float64 = 11.0
	var n4 float64 = 17.0
	if n3 > 10.0 && n4 < 20.0 {
		fmt.Println("输出两数之和 =", (n3+n4))
	}
	
	//判断两者之和是否能被3又能被5整除
	var n5 int32 = 10
	var n6 int32 = 5
	if (n5 + n6) % 3 == 0 && (n5 + n6) % 5 ==0 {
		fmt.Println("能被3和5整除")
	}
}

输出结果如下图所示:

在这里插入图片描述

错误案例1:编译错误,缺少括号{}

  • syntax error: unexpected newline, expecting { after if clause

在这里插入图片描述

错误案例2:编译错误,else不能换行

  • syntax error: unexpected else, expecting }

在这里插入图片描述


3.多分支控制

基本语法如下:

if 条件表达式1 {
	执行代码块1
} else if 条件表达式2 {
	执行代码块2
}
...
 else {
 	执行代码块n
}

说明:

  • 先判断条件表达式1是否成立,如果为True,就执行代码块1
  • 如果条件表达式1位False,就去判断条件表达式2是否成立,如果条件表达式2成立,就执行代码块2
  • 依次类推,如果所有的条件表达式不成立,就执行else语句块
  • else不是必须的
  • 注意:多分支语句只能有一个执行入口

对应的流程图如下所示:

在这里插入图片描述

案例分析:编写代码实现考试成绩判断,如果成绩大于等于90则为A,如果成绩[80,90)则为B,依次类推不及格为E。

package main
import "fmt"

func main() {
	//输入变量
	var score int
	fmt.Println("请输入成绩:")
	fmt.Scanln(&score)

	//多分支判断
	if score >= 90 {
		fmt.Println("该同学成绩为A")
	} else if score >=80 && score < 90 {
		fmt.Println("该同学成绩为B")
	} else if score >=70 && score < 80 {
		fmt.Println("该同学成绩为C")
	} else if score >=60 && score < 70 {
		fmt.Println("该同学成绩为D")
	} else {
		fmt.Println("该同学成绩为E")
	}
	fmt.Printf("成绩为:%d", score)
}

输出结果如下图所示:

在这里插入图片描述

注意事项:

  • 初学者需要注意多分支语句的条件判断,经常会陷入判断融合的情况,比如下图只会输出“ok1”。

在这里插入图片描述

案例1:融合bool类型多分支判断

package main
import "fmt"

func main() {
	//多分支判断
	var b bool = true
	if b == false {
		fmt.Println("a")
	} else if b {
		fmt.Println("b")
	} else if !b {
		fmt.Println("c")
	} else {
		fmt.Println("d")
	}
}

输出结果为“b”,如果将第一个判断修改成“b=false”是否能编译通过呢?答案是否,它会提示编译错误,因为if条件表达式不能是赋值语句。

在这里插入图片描述

案例2:输入一个字符,判断:

  • 它是否为大写字母,如果是转换成小写;
  • 它是否为小写字母,如果是转换层大写;
  • 否则,输出原字符
package main
import "fmt"

func main() {
	var ch byte
	var res byte
	fmt.Println("请输入字母:")
	fmt.Scanf("%c", &ch)

	//大小写转换
	if ch >= 'A' && ch <= 'Z' {
		res = ch + 32
	} else if ch >= 'a' && ch <= 'z' {
		res = ch - 32
	} else {
		res = ch
	}
	fmt.Printf("输入字母:%c %v \n", ch, ch)
	fmt.Printf("输出结果:%c %v \n", res, res)
}

输出结果如下图所示,这道题目非常棒,希望大家熟练掌握。知识点包括:

  • ASCII码大小写转换方法
  • 多分支条件语句
  • char字符型变量输入输出

在这里插入图片描述


4.嵌套分支

在一个分支结果中又完整嵌套另一个完整的分支结构,里面的分支结构称为内层分支,外面的分支结构称为外层分支。基本语法如下:

if 条件表达式 {
	if 条件表达式 {
		语句块
	} else {
		语句块
	}
	....
}

注意事项:

  • 嵌套分支不宜过多,建议控制在三层内

案例分析:

  • 参加百米运动会,如果用时8秒以内进入决赛,否则提示淘汰;并且根据性别提示进入男子组或女子组,我们输入成绩和性别进行相关判断。
package main
import "fmt"

func main() {
	var sex string
	var second float64

	fmt.Println("请输入秒数:")
	fmt.Scanln(&second)

	//嵌套分支
	if second <=8 {
		fmt.Println("请输入性别:")
		fmt.Scanln(&sex)
		if sex == "男" {
			fmt.Println("进入决赛的男子组")
		} else if sex == "女" {
			fmt.Println("进入决赛的女子组")
		} else {
			fmt.Println("性别输入错误")
		}
	} else {
		fmt.Println("淘汰未进入决赛")
	}
}

输出结果如图所示:

在这里插入图片描述


三.switch分支控制

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

基本语法如下:

switch 表达式 {

case 表达式1, 表达式2, ...:
	语句块1
case 表达式3, 表达式4, ...:
	语句块2
	....
default:
    语句块n
}

对应的流程图如下所示:

  • switch的执行流程是先执行表达式,得到值,然后和case的表达式进行比较,如果相等,就匹配到;接着执行对应case的语句块,然后退出switch控制。
  • 如果switch表达式的值没有和任何case的表达式匹配成功,则执行default的语句块,执行后退出switch的控制。
  • golang中的case后的表达式可以有多个,使用逗号间隔。
  • golang中的case语句块不需要写break,因为默认会有。即在默认情况下,当程序执行完case语句块后,就直接退出该switch控制结构。

在这里插入图片描述

下面简单实现一个switch语句案例。请编写程序实现输入某个字符,然后a表示周一,b表示周二,c表示周三,根据用户的输入依次显示信息。

package main
import "fmt"

func main() {
	var key byte
	fmt.Println("请输入a到g的一个字符")
	fmt.Scanf("%c", &key)

	//switch语句
	switch key {
		case 'a':
			fmt.Println("今天星期一")
		case 'b':
			fmt.Println("今天星期二")
		case 'c':
			fmt.Println("今天星期三")
		case 'd':
			fmt.Println("今天星期四")
		case 'e':
			fmt.Println("今天星期五")
		case 'f':
			fmt.Println("今天星期六")
		case 'g':
			fmt.Println("今天星期天")
		default:
			fmt.Println("输入有误....")
	}
}

输出结果如下图所示:

在这里插入图片描述

注意事项:
(1) case和switch后是一个表达式,即常量值、变量、一个有返回值的函数等

在这里插入图片描述

(2) case后的各个表达式值的数据类型,必须和switch的表达式数据类型一致

在这里插入图片描述

(3) case后面可以带多个表达式,使用逗号间隔,如下图所示:

在这里插入图片描述

(4) case后的表达式如果是常量值,则要求不能重复

在这里插入图片描述

(5) case后面不需要带break,程序匹配到一个case后就会执行对应的代码块,然后退出switch,如果一个都匹配不到,则执行default

(6) default语句不是必须的

(7) switch后也可以不带表达式,类似于if-else分支来使用;同时case中也可以对范围进行判断

package main
import "fmt"

func main() {
	//switch后不接表达式 类似于if-else分支来使用
	var age int = 10

	switch {
		case age == 10:
			fmt.Println("年龄为10")
		case age == 20:
			fmt.Println("年龄为20")
		default:
			fmt.Println("没有匹配到")
	}

	//case中也可以对范围进行判断
	var score int = 90
	switch {
		case score > 90:
			fmt.Println("成绩优秀...")
		case score >= 70 && score <= 90:
			fmt.Println("成绩良好...")
		case score >=60 && score <70:
			fmt.Println("成绩及格...")
		default:
			fmt.Println("不及格")
	}
}

(8) switch后也可以直接声明定义变量,分好结束,但不推荐使用。

在这里插入图片描述

(9) switch穿透fallthrough。如果在case语句块后增加fallthrough,则会继续执行下一个case,也叫switch穿透。

package main
import "fmt"

func main() {
	//switch穿透fallthrough
	var age int = 10

	switch age {
		case 10:
			fmt.Println("年龄为10")
			fallthrough   //默认只能穿透一层
		case 20:
			fmt.Println("年龄为20")
			fallthrough
		case 30:
			fmt.Println("年龄为30")
		default:
			fmt.Println("没有匹配到")
	}

}

输出结果如下图所示:

在这里插入图片描述

(10) Type Switch。switch语句还可以被用于type-switch来判断某个interface(接口)变量中实际指向的变量类型。后续文章会补充interface。

package main
import "fmt"

func main() {
	//type-switch
	var x interface{}     //定义空接口
	var y = 10.0
	x = y

	switch i := x.(type) {
		case nil:
			fmt.Printf("x的类型是:%T", i)
		case int:
			fmt.Printf("x是int型")
		case float64:
			fmt.Printf("x是float64型")   //输出结果
		case func(int) float64:
			fmt.Printf("x是func(int)型")
		case bool, string:
			fmt.Printf("x是bool或string型")
		default:
			fmt.Println("未知类型")
	}
}

最后简单总结switch和if的区别:

  • 如果判断的具体数值不多,而且符合整数、浮点数、字符、字符串这几种类型,建议使用switch语句,简洁高效。
  • 其他情况:对区间判断和结果为bool类型的判断使用if,并且if的使用范围更广。
  • 作者个人习惯是使用if语句,很少用到switch语句。

四.编程练习

1.题目

(1) 判断一个年份是否是闰年,闰年的条件是符合以下二者之一。

  • 年份能被4整除,但不能被100整除
  • 年份能被400整除

(2) 请分别使用if和switch语句实现成绩判断,输出分数对应的等级。

  • [100, 90] => A
  • [80, 90) => B
  • [70, 80) => C
  • [60, 70) => D
  • [0, 60) => E

(3) 根据淡旺季的月份和年龄,实现一个票价系统。

  • 旺季:4-10月
    成人(18-60岁):60
    儿童(<18):半价
    老人(>60):1/3
  • 淡季
    成人:40
    其他:20

(4) 使用switch语句实现:根据用户输入月份,输出对应春夏秋冬季节。

(5) 求ax^2+bx+c=0方程的根。a、b、c分别为函数的参数,如果b^2-4ac>0,则有两个解;如果b^2-4ac=0,则有一个解;否则无解。

  • 提示:x1=(-b+sqrt(b^2-4ac))/2a
  • 提示:x2=(-b-sqrt(b^2-4ac))/2a

2.答案

(1) 判断一个年份是否是闰年,闰年的条件是符合以下二者之一。

  • 年份能被4整除,但不能被100整除
  • 年份能被400整除

代码如下:

package main
import "fmt"

func main() {
	//判断闰年
	var year int
	fmt.Println("请输入年份:")
	fmt.Scanln(&year)

	if (year % 4 == 0 && year % 100 !=0) || year % 400 == 0 {
		fmt.Println(year, "是闰年~")
	} else {
		fmt.Println(year, "不是闰年~")
	}
}

输出结果如下图所示:

在这里插入图片描述


(2) 请分别使用if和switch语句实现成绩判断,输出分数对应的等级。

  • [100, 90] => A
  • [80, 90) => B
  • [70, 80) => C
  • [60, 70) => D
  • [0, 60) => E

代码如下:

package main
import "fmt"

func main() {
	var score int
	fmt.Println("请输入分数:")
	fmt.Scanln(&score)

	//if判断
	if score >= 90 {
		fmt.Println("分数等级为A")
	} else if score >= 80 && score < 90 {
		fmt.Println("分数等级为B")
	} else if score >= 70 && score < 80 {
		fmt.Println("分数等级为C")
	} else if score >= 60 && score < 70 {
		fmt.Println("分数等级为D")
	} else {
		fmt.Println("不及格等级为E")
	}

	//switch判断
	switch {
		case score > 90:
			fmt.Println("分数等级为A")
		case score >= 80 && score < 90:
			fmt.Println("分数等级为B")
		case score >=70 && score < 80:
			fmt.Println("分数等级为C")
		case score >=60 && score < 70:
			fmt.Println("分数等级为D")
		default:
			fmt.Println("不及格等级为E")
	}
}

输出结果如下图所示:
在这里插入图片描述


(3) 根据淡旺季的月份和年龄,实现一个票价系统。

  • 旺季:4-10月
    成人(18-60岁):60
    儿童(<18):半价
    老人(>60):1/3
  • 淡季
    成人:40
    其他:20

代码如下:

package main
import "fmt"

func main() {
	//出票系统
	var month byte
	var age byte
	var price float64 = 60.0

	fmt.Println("请输入游玩月份:")
	fmt.Scanln(&month)
	fmt.Println("请输入游客年龄:")
	fmt.Scanln(&age)

	if month >= 4 && month <= 10 {
		//旺季
		if age > 60 {
			fmt.Printf("%v月 票价 %v 年龄 %v \n", month, price / 3, age)
		} else if age >= 18 {
			fmt.Printf("%v月 票价 %v 年龄 %v \n", month, price, age)
		} else {
			fmt.Printf("%v月 票价 %v 年龄 %v \n", month, price / 2, age)
		}
	} else {
		//淡季
		if age >= 18 && age < 60 {
			fmt.Println("淡季成人票价 40")
		} else {
			fmt.Println("淡季儿童和老人票价 20")
		}
	}
}

输出结果如下图所示:

在这里插入图片描述


(4) 使用switch语句实现:根据用户输入月份,输出对应春夏秋冬季节。

代码如下:

package main
import "fmt"

func main() {
	//季节判断
	var month byte
	fmt.Println("请输入月份:")
	fmt.Scanln(&month)

	switch month {
		case 3, 4, 5:
			fmt.Println("Spring")
		case 6, 7, 8:
			fmt.Println("Summer")
		case 9, 10, 11:
			fmt.Println("Autumn")
		case 12, 1, 2:
			fmt.Println("Winter")
		default:
			fmt.Println("Error Input")
	}
}

输出结果如下图所示:

在这里插入图片描述


(5) 求ax^2+bx+c=0方程的根。a、b、c分别为函数的参数,如果b^2-4ac>0,则有两个解;如果b^2-4ac=0,则有一个解;否则无解。

  • 提示:x1=(-b+sqrt(b^2-4ac))/2a
  • 提示:x2=(-b-sqrt(b^2-4ac))/2a

注意,需要引入math.Sqrt(num)即可求平方根

package main
import "fmt"
import "math"

func main() {
	/* 
	 分析思路
	   1) a,b,c是给出的变量
	   2) 使用给出的数学公式和多分支语句计算
	   3) 导入math包计算平方根
	*/
	var a float64
	var b float64
	var c float64
	fmt.Println("请输入abc三个变量")
	fmt.Scanf("%f %f %f", &a, &b, &c)
	fmt.Printf("a=%v b=%v c=%v \n", a, b, c)

	m := b * b - 4 * a * c
	if m > 0 {
		x1 := (-b + math.Sqrt(m)) / (2 * a)
		x2 := (-b - math.Sqrt(m)) / (2 * a)
		fmt.Printf("x1=%v x2=%v", x1, x2)
	} else if m == 0 {
		x1 := (-b + math.Sqrt(m)) / (2 * a)
		fmt.Printf("x1=%v", x1)
	} else {
		fmt.Printf("无解")
	}
}

输出结果如下图所示:

在这里插入图片描述


五.总结

写到这里,这篇基础性Golang文章介绍完毕,希望您喜欢!祝大家新年快乐,牛气冲天,也希望自己能分享更优秀、更深入的文章。

  • 一.顺序控制语句
  • 二.条件控制语句
    1.单分支控制
    2.双分支控制
    3.多分支控制
    4.嵌套分支
  • 三.switch分支控制
  • 四.编程练习
    1.题目
    2.答案

Go基本运算和进制转换了解后,后面的文章将详细介绍Go语言的条件语句和循环语句知识,并结合案例进行普及。希望这篇基础性文章对您有帮助,写得不好的地方还请海涵。同时非常感谢参考文献中的大佬们的文章分享,尤其是韩顺平老师,深知自己很菜,得努力前行。也希望自己能深入下去,未来四年好好研究Go编程语言,做更多实际工程,写更好的文章,共勉!

源代码下载地址:

2020年在github的绿瓷砖终于贴完了第一年提交2100余次,获得1500多+stars,开源93个仓库,300个粉丝。挺开心的,希望自己能坚持在github打卡五年,督促自己不断前行。简单总结下,最满意的资源是YQ爆发时,去年2月分享的舆情分析和情感分析,用这系列有温度的代码为武汉加油;最高赞的是Python图像识别系列,也获得了第一位来自国外开发者的贡献补充;最花时间的是Wannacry逆向系列,花了我两月逆向分析,几乎成为了全网最详细的该蠕虫分析;还有AI系列、知识图谱实战、CVE复现、APT报告等等。当然也存在很多不足之处,希望来年分享更高质量的资源,也希望能将安全和AI顶会论文系列总结进来,真诚的希望它们能帮助到大家,感恩有你,一起加油~

在这里插入图片描述

感谢华为云的礼物,希望能与大家一起在华为云社区共同进步,且看且珍惜。

原文地址:https://blog.csdn.net/Eastmount/article/details/113804706

(By:娜璋AI之家 Eastmount 2021-08-10 星期二 夜于贵阳 )


参考文献:

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。