一. 常量
1.1 常量的定义和使用
在讲解常量之前,我们要先简单说一下我们前面讲解的变量。我们都知道,变量是用来存储数据,并且变量里面存储的值是可以在程序运行时随时发生变化的。那么什么是常量呢?在程序运行过程中其值不能发生改变的量就是常量。
常量在定义时,必须给初始值,不能改变常量的值,不能获取常量地址,建议常量名为大写和变量区分。
代码如下:
func main() {
//变量的定义
//var 变量名 数据类型 = 值
b := 9
//常量的定义
//const 常量名 数据类型 = 值
const a int = 10
//不能改变常量的值
//a = 20 //error
//不能获取常量的内存地址
//fmt.Println(&a) //error
//常量可以参与程序计算
b = a * b
fmt.Println(a)
fmt.Println(b)
}
通过自动推导类型创建常量
func main() {
//常量的自动推导类型
//const 常量名 = 值
const a = 10
fmt.Println(a)
fmt.Printf("%T", a)
}
问题:什么场景下会用到常量呢?
在程序开发中,我们用常量存储一直不会发生变化的数据,例如:π,身份证号码等。像这类的数据,在整个程序中运行中都是不允许发生改变的。
1.2 字面常量
所谓字面常量(literal),是指程序中硬编码的常量,如:
package main
import "fmt"
func main() {
//字面常量 (硬编码常量)
fmt.Println("hello")
fmt.Println(10)
fmt.Println(3.14)
fmt.Printf(true)
}
1.3 iota枚举
常量声明可以使用iota常量生成器初始化,它用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。
注意:在一个const声明语句中,在第一个声明的常量所在的行,iota将会被置为0,然后在每一个有常量声明的行加一。
具体使用方式如下:
func main() {
//在iota枚举中,在第一个声明的常量所在的行,iota将会被置为0,每换一行值+1
//iota给常量赋值使用
const (
a = iota
b = iota
c = iota
)
fmt.Printf("a=%d,b=%d,c=%d\n", a, b, c)
//iota遇到const,重置为0
const d = iota
fmt.Printf("d=%d\n", d)
//在iota枚举中,同一行的值相同
const (
a1 = iota
b1, c1 = iota, iota
d1 = iota
)
fmt.Printf("a1=%d,b1=%d,c1=%d,d1=%d\n", a1, b1, c1, d1)
//在iota枚举中,除第一行外,其他枚举值不用赋值
const (
a2 = iota
b2
c2
d2
)
fmt.Printf("a2=%d,b2=%d,c2=%d,d2=%d\n", a2, b2, c2, d2)
const (
a3 = iota
b3 = 3
c3 = iota
d3 = 7
)
fmt.Printf("a3=%d,b3=%d,c3=%d,d3=%d\n", a3, b3, c3, d3)
}
结果如下:
a=0,b=1,c=2
d=0
a1=0,b1=1,c1=1,d1=2
a2=0,b2=1,c2=2,d2=3
a3=0,b3=3,c3=2,d3=7
二.运算符
前面已经介绍了变量,常量,那么接下来我们学习一下运算符。Go语言中常见的运算符有算术运算符,赋值运算符,关系运算符,逻辑运算符等。
2.1 算术运算符
运算符 | 术语 | 示例 | 结果 |
+ | 加 | 10 + 5 | 15 |
- | 减 | 10 - 5 | 5 |
* | 乘 | 10 * 5 | 50 |
/ | 除 | 10 / 5 | 2 |
% | 取模(取余) | 10 % 3 | 1 |
++ | 后自增,没有前自增 | a=0; a++ | a=1 |
-- | 后自减,没有前自减 | a=2; a-- | a=1
|
算术表达式:由算术运算符连接起来的式子.如:1+1 a-b(变量ab前面已声明并赋初值)
示例如下:
func main() {
a := 10
b := 3
//两个整数相除,得到的结果也是整数
fmt.Println(a / b)
}
结果如下:
3
func main() {
a := 10
b := 3
fmt.Println(a % b)
}
结果如下:
1
func main() {
a := 3
b := 4
a++
b--
fmt.Printf("a=%d,b=%d", a, b)
}
结果如下:
a=4,b=3
2.2 类型转换
在Go语言中,不同类型的变量不允许计算;如果要计算,需要强制类型转换。
强制类型转化:数据类型(变量) 或 数据类型(表达式)
示例如下:
func main() {
var a, b, c int
num := 3
fmt.Print("请输入三个值:")
fmt.Scan(&a, &b, &c)
sum := a + b + c
fmt.Printf("sum=%d\n", sum)
//强制类型转化
//数据类型(变量) 数据类型(表达式)
avg := float64(sum) / float64(num)
fmt.Printf("avg=%.2f\n", avg)
}
结果如下:
请输入三个值:1 2 3
sum=6
avg=2.00
func main() {
weight := 5
price := 3.25
//在Go语言中,不同类型的变量不允许计算;如果要计算,需要强制类型转换
fmt.Println(float64(weight) * price)
//将浮点类型转换为整型会丢弃小数部分,只保留整数部分
fmt.Println(weight * int(price))
}
结果如下:
16.25
15
强制类型转换,数据类型一定要相兼容
2.3 赋值运算符
关于赋值运算符前面我们已经使用过多次,赋值运算符 = ,var int num = 9;num = num + 1;这里的 = 号是赋值运算符,不是数学义意上的相等。常见的赋值运算符如下,前面我们使用的 = 是普通赋值,+=,-=等我们称为“复合赋值运算符”。
运算符 | 说明 | 示例 |
= | 普通赋值 | c = a + b 将a + b 表达式结果赋值给c |
+= | 相加后再赋值 | c += a 等价于c = c + a |
-= | 相减后再赋值 | c -= a 等价于c = c - a |
*= | 相乘后再赋值 | c *= a 等价于c = c * a |
/= | 相除后再赋值 | c /= a 等价于c = c / a |
%= | 求余后再赋值 | c %= a 等价于c = c % a |
示例如下:
unc main() {
a := 10
b := 20
a += b //a = a + b
fmt.Printf("a=%d\n", a)
a -= b //a = a - b
fmt.Printf("a=%d\n", a)
a *= b //a = a * b
fmt.Printf("a=%d\n", a)
a /= b //a = a / b
fmt.Printf("a=%d\n", a)
a %= b //a= a % b
fmt.Printf("a=%d\n", a)
}
结果如下:
a=30
a=10
a=200
a=10
a=10
2.4 关系运算符
关系运算符我们又称为比较运算符,听到比较这个词,大家想到的就是比较大小,例如:
大象的重量(1500)>老鼠的重量(1)
兔子的寿命(3)>乌龟的寿命(1000)
我的年龄(20)==你的年龄(20)
提问:比大比小的结果是什么?
结果是对或者是错,在GO语言中,怎样表示对于错呢?
关系运算的结果是布尔类型的。
bool值只有两个
真:true
假:false
GO语言中常见的关系运算符如下:
运算符 | 术语 | 示例 | 结果 |
== | 相等于 | 4 == 3 | false |
!= | 不等于 | 4 != 3 | true |
< | 小于 | 4 < 3 | false |
> | 大于 | 4 > 3 | true |
<= | 小于等于 | 4 <= 3 | false |
>= | 大于等于 | 4 >= 1 | true |
由以上关系运算符链接的表达式我们称为关系表达式。
关系运算符具体使用方式如下:
func main() {
a := 10
b := 20
//%t 是一个占位符,表示输出一个布尔类型值
fmt.Printf("a < b:%t\n", a < b)
fmt.Printf("a > b:%t\n", a > b)
fmt.Printf("a <= b:%t\n", a <= b)
fmt.Printf("a >= b:%t\n", a >= b)
fmt.Printf("a == b:%t\n", a == b)
fmt.Printf("a != b:%t\n", a != b)
}
结果如下:
a < b:true
a > b:false
a <= b:true
a >= b:false
a == b:false
a != b:true
2.5 逻辑运算符
常见的逻辑运算符如下
运算符 | 术语 | 示例 | 结果 |
! | 非 | !a | 如果a为假,则!a为真; 如果a为真,则!a为假。 |
&& | 与 | a && b | 如果a和b都为真,则结果为真,否则为假。 |
|| | 或 | a || b | 如果a和b有一个为真,则结果为真,二者都为假时,结果为假。 |
有逻辑运算符连接的表达式叫做逻辑表达式
通过以上表格我们发现:逻辑表达式的结果同样也是bool类型
逻辑运算符两边放的一般都是关系表达式或者bool类型的值。
例如:
5>3 &&true
3>5||false
示例如下:
func main() {
a := 10
b := 20
//逻辑非:!,布尔值取反
fmt.Println(!(a > b))
a1 := true
b1 := false
//逻辑与:&&,同真为真,其余为假
fmt.Println(a1 && b1)
atk := 10000
lv := 20
//逻辑或:||,同假为假,其余为真
fmt.Println(atk >= 10000 || lv > 10)
}
结果如下:
true
false
true
总结:
逻辑与:&&
表达式1&&表达式2
表达式1 | 表达式2 | 表达式1&&表达式2 |
True | True | True |
False | True | False |
True | False | False |
False | False | false |
逻辑或:||
表达式1||表达式2
表达式1 | 表达式2 | 表达式1||表达式2 |
True | True | True |
True | False | True |
False | True | True |
False | False | false |
逻辑非:!
!表达式
表达式 | !表达式 |
True | False |
False | true |
2.6 其他运算符
运算符 | 术语 | 示例 | 说明 |
& | 取地址运算符 | &a | 变量a的地址 |
* | 取值运算符 | *a | 指针变量a所指向内存的值 |
示例如下:
func main() {
//&,取地址运算符 引用运算符
//*,取值运算符 解引用运算符
a := 10
fmt.Println(&a)
fmt.Printf("%p\n", &a)
var p *int = &a
fmt.Println(p)
*p = 123
fmt.Println(*p)
}
结果如下:
0xc00007e008
0xc00007e008
0xc00007e008
123
2.7运算符优先级
1、特殊运算符
() [] .
2、单目运算符
! ++ -- & *
3、双目运算符
3、1 算数运算符
* / %
+ -
3、2 关系运算符
> >= < <= == !=
3、3 逻辑运算符
&&
||
3、4 赋值运算符
= += -= *= /= %=
三.流程控制
前面我们写的程序都是从第一行开始执行,一直执行到末尾,一行一行的顺序执行下来,这种执行结构叫顺序执行结构。
GO语言除了有顺序结构,还有选择结构,循环结构。
- 顺序结构:程序按顺序执行,不发生跳转。
- 选择结构:依据是否满足条件,有选择的执行相应功能。
- 循环结构:依据条件是否满足,循环多次执行某段代码。
下面先讲解选择结构:
3.1 选择结构
选择结构我们也称为判断结构。
如果某些条件满足,才能做某件事情,而不满足时不允许做,这就是所谓的判断。
3.1.1 if结构
在编程中实现选择判断结构就是用if。
if结构基本语法:
if 条件判断{
代码语句
},
条件判断如果为真(true),那么就执行大括号中的语句,如果为假(false),就不执行大括号中的语句,(大家可以想一下,什么样的表达式返回的结果要么为true,要么为false),继续执行if结构后面的代码。
具体案例如下:
func main() {
var score int
fmt.Scan(&score)
if score > 700 {
fmt.Println("我要上清华")
}
}
结果如下:
710
我要上清华
GO语言相比其它语言要灵活很多,下面我们看一下if的另外一种语法格式:
func main() {
//if支持初始化语句和判断语句在一起;二者以分号分隔
if a := 10; a == 10 {
fmt.Println("a == 10")
}
}
结果如下:
a == 10
3.1.2 if else结构
想一想:在使用if的时候,它只能做到满足条件时要做的事情。那万一需要在不满足条件的时候,做某些事,该怎么办呢?
例如:小赵的考试成绩大于90(含)分,那么爸爸奖励他100元钱,否则的话,爸爸就让小赵跪方便面。
有同学可能会想,这道题用if结构也可以实现。如下所示:
func main() {
var score float64
fmt.Print("请输入考试成绩:")
fmt.Scanf("%f",&score)
if score >= 90{
fmt.Println("奖励100元")
}
if score < 90{
fmt.Println("跪方便面")
}
}
虽然以上代码可以实现,但是比较麻烦,我们可以使用更简单的方式:else
结构如下:
if 条件判断{
代码语句1
}else{
代码语句2
}
首先先执行if后面的条件判断,如果条件判断成立(结果为真),执行if后面的代码语句1,代码语句1执行完成后,表示整个if---else--结构结束了(else后面的代码语句2不会执行),继续执行后面的代码。如果if后面的条件判断不成立也就是结果为假,那么if后面的代码语句1不会被执行,这时会执行else后面的代码语句2,执行完后,表示整个if—else—结构执行结束了,再执行后续的代码。
下面我们通过if---else结构完成上面的案例。
func main() {
var score float64
fmt.Print("请输入考试成绩:")
fmt.Scanf("%f", &score)
if score >= 90 {
fmt.Println("奖励100元")
} else {
fmt.Println("跪方便面")
}
}
3.1.3 if嵌套
我们上面的案例中,使用的是if-else的基本结构,其实if-else结构还可以进行嵌套使用。
例如:输入公交卡当前的余额,只要超过2元,就可以上公交车;如果空座位的数量大于0,就可以坐下。
func main() {
var money float64
fmt.Println("请输入公交卡钱数:")
fmt.Scanf("%f\n",&money)
if money >= 2{
var seat_count int
fmt.Println("请输入空座位数量:")
fmt.Scanf("%d",&seat_count)
if seat_count > 0 {
fmt.Println("请坐")
}else {
fmt.Println("不好意思,你只能站着了!!")
}
}else {
fmt.Println("余额不足")
}
}
以上案例在if中嵌套了if-else结构,同理在else也可以嵌套if-else结构,这个要根据实际情况确定。下面我们看如下题目:
对学员的结业考试成绩评测(大家考虑用if好还是用if-else好)
成绩>=90 :A
90>成绩>=80 :B
80>成绩>=70 :C
70>成绩>=60 :D
成绩<60 :E
我们先使用if来实现上面的问题:
func main() {
var score int
fmt.Println("请输入考试成绩:" )
fmt.Scanf("%d",&score)
if score >= 90{
fmt.Println("A")
}
if score < 90 && score >= 80{
fmt.Println("B")
}
if score < 80 && score >= 70{
fmt.Println("C")
}
if score < 70 && score >= 60{
fmt.Println("D")
}else{
fmt.Println("E")
}
}
上面的代码我们最后发现都会输出“E”,为什么呢?
解决方案如下:
func main() {
var score int
fmt.Println("请输入考试成绩:" )
fmt.Scanf("%d",&score)
if score >= 90{
fmt.Println("A")
}
if score < 90 && score >= 80{
fmt.Println("B")
}
if score < 80 && score >= 70{
fmt.Println("C")
}
if score < 70 && score >= 60{
fmt.Println("D")
}
if score < 60{
fmt.Println("E")
}
}
下面我们来使用 if-else 结构来解决上面的问题
案例演示如下:
func main() {
var score int
fmt.Println("请输入考试成绩:")
fmt.Scanf("%d",&score)
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")
}
}
}
}
}
面的代码虽然满足了我们的需求,但是嵌套的代码非常多,可读性比较差,我们在以后的编程工作中尽量避免这种多重嵌套。
通过这道题,我们发现在这种多条件判断应用的场景中不太适合通过 if(适合一种条件判断的情况)或者是if-else(适合两种条件判断的情况或者是判断条件不是很多的场景)进行判断。
上面的题目更好的方法:if-else if结构
3.1.4 if-else if结构
基本语法如下:
if 条件判断{
要执行的代码段
}else if 条件判断{
要执行的代码段
}else if 条件判断{
要执行的代码段
}else if条件判断{
要执行的代码段
}.else{
}
通过以上的语法格式我们发现,可以写很多的else if结构。
具体的执行过程:程序首先判断第一个if所带的小括号中的判断条件,如果条件成立,也就是返回一个true,则执行该if所带的大括号中的代码,执行完成后,立即跳出if else-if结构。如果第一个if所带的判断条件不成立,也就是返回一个false,则继续向下进行判断,依次的判断每一个if所带的判断条件,如果成立,就执行该if所带的大括号中的代码,如果不成立,则继续向下判断,如果每个if所带的判断条件都不成立,就看当前这个if else-if结构中是否存在else。如果有else的话,则执行else中所带的代码,如果没有else,则整个 if-else if什么都不做。else可以省略。
下面我们使用该结构完成上面的案例:
func main() {
var score int
fmt.Println("请输入考试成绩:")
fmt.Scanf("%d",&score)
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")
}
}
总结:我们通过前面的案例讲解,大家应该能够总结出if结构,if-else结构和if-else if结构应用的场景.
if结构适合:一种的判断
if-else结构适合:两种情况的判断
if-else if 结构适合:多种情况判断,并且判断都是对区间中的数据进行判断(例如:考试成绩)
3.1.5 switch结构
下面我们开始讲解选择中的另外一个结构就是switch结构。
在讲解switch结构之前,我们先来看如下问题:
李四的年终工作评定,如果定为A级,则工资涨500元,如果定为B级,则工资涨200元,如果定为C级,工资不变,如果定为D级工资降200元,如果定为E级工资降500元.
设李四的原工资为5000,请用户输入李四的评级,然后显示李四来年的工资.
大家看到如上题目,肯定想到的是用if-else if结构来实现,那么具体案例实现如下:
func main() {
var salary int = 5000
var level string
fmt.Println("请输入李四的年终评定:")
fmt.Scanf("%s",&level)
if level == "A"{
salary += 500
}else if level == "B"{
salary += 200
}else if level == "C"{
}else if level == "D"{
salary -= 200
}else if level == "E"{
salary -= 500
}else {
fmt.Println("输入错误,程序推迟")
}
fmt.Println("李四来年的工资是:",salary)
}
虽然以上代码实现了我们的需求,但是我们发现了一个问题,如果输入其它字符(例如:输入字符T),我们发现最终的结果不仅输出了“输入错误,程序退出”,同时还输出了“李四来年的工资是:5000”。如果输入错误了,这句话是不应该输出的,那么应该怎样进行处理呢?
func main() {
var salary int = 5000
var level string
var status bool = true
fmt.Println("请输入李四的年终评定:")
fmt.Scanf("%s",&level)
if level == "A"{
salary += 500
}else if level == "B"{
salary += 200
}else if level == "C"{
}else if level == "D"{
salary -= 200
}else if level == "E"{
salary -= 500
}else {
status = false
fmt.Println("输入错误,程序推迟")
}
if status{
fmt.Println("李四来年的工资是:",salary)
}
}
通过上面的代码,我们实际上是定义了一个bool类型的变量,默认值为true,当输入评定级别错误时,将其改为false.最后在输出工资时,做了判断,如果条件成立表示输入了正确的评定级别,所以输出对应的工资,否则不输出工资。
我们前面在讲解if-else if结构时讲过,该结构适合什么场合:1.多条件判断,2:区间性的数据判断。但是我们看一下该案例,是否是对区间性的数据进行判断呢?不是,而是定值判断,也就是对一个固定值的判断。
对这种固定值的判断推荐使用switch-case结构。
switch-case结构语法如下:
switch 变量或者表达式的值{
case 值1:
要执行的代码
case 值2:
要执行的代码
case 值3:
要执行的代码
………………………………..
default:
要执行的代码
}
switch-case结构的执行流程:
程序执行到switch处,首先将变量或者表达式的值计算出来,然后拿着这个值依次跟每个case后面所带的值进行匹配,一旦匹配成功,则执行该case所带的代码,执行完成后,跳出switch-case结构。如果,跟每个case所带的值都不匹配。就看当前这个switch-case结构中是否存在default,如果有default,则执行default中的语句,如果没有default,则该switch-case结构什么都不做。
基本案例演示如下:
func main() {
var score int = 30
switch score {
case 90:
fmt.Println("优秀")
case 80:
fmt.Println("良好")
case 70:
fmt.Println("一般")
case 60:
fmt.Println("及格")
default:
fmt.Println("不及格")
}
}
另外一种语法格式如下:
func main() {
var score int
fmt.Scan(&score)
switch score / 10 {
//如果多个分支执行相同代码 可以在一个case中将多个值用逗号分隔
case 10, 9:
fmt.Println("A")
case 8:
fmt.Println("B")
case 7:
fmt.Println("C")
case 6:
fmt.Println("D")
default:
fmt.Println("E")
}
}
注意:某个case 后面跟着的代码执行完毕后,不会再执行后面的case,而是跳出整个switch结构, 相当于每个case后面都跟着break(终止),但是如果我们想执行完成某个case后,强制执行后面的case,可以使用fallthrough。
func main() {
var m int
fmt.Scan(&m)
day := 0
switch m {
case 1:
//在当前分支执行结束后在继续执行下一个分支
fallthrough
case 3:
fallthrough
case 5:
fallthrough
case 7:
fallthrough
case 8:
fallthrough
case 10:
fallthrough
case 12:
day = 31
case 2:
day = 28
}
fmt.Println(day)
}
下面我们用switch-case结构来实现开头的案例,示例如下:
func main() {
var salary int = 5000
var level string
var status bool = true
fmt.Println("请输入李四的年终评定:")
fmt.Scanf("%s",&level)
switch level {
case "A":
salary += 500
case "B":
salary += 200
case "C":
case "D":
salary -= 200
case "E":
salary -= 500
default:
status = false
fmt.Println("输入错误,程序退出!")
}
if status{
fmt.Println("李四的工资是:",salary)
}
}
3.1.6 if - else if 与 switch的比较
其实通过上面的案例,我们发现switch能够实现的,我们用if-else if也可以实现,那么反过来呢,if-else if能实现的,我们使用switch能否实现呢?接下来将我们前面用if-else if实现的“考试成绩评定”这道题用switch来实现。
func main(){
var score int
fmt.Println("请输入考试成绩:")
fmt.Scanf("%d",&score)
switch {
case score >= 90:
fmt.Println("A")
case score >= 80:
fmt.Println("B")
case score >= 70:
fmt.Println("C")
case score >= 60:
fmt.Println("D")
default:
fmt.Println("E")
}
}
总结:
相同点:都可以实现多分支结构
不同点(根据个人习惯进行选择):
if-else if:可以处理范围
switch:一般用于等值比较
下面我们通过一个练习题,将if-else和switch结构进行综合应用
练习:请用户输年份,再输入月份,输出该月的天数。
func main() {
var year int
var mouth int
var day int
fmt.Println("请输入年份:")
fmt.Scanf("%d\n",&year)
fmt.Println("请输入月份:")
fmt.Scanf("%d",&mouth)
if mouth >= 1 && mouth <= 12 {
switch mouth {
case 1,3,5,7,8,10,12:
day = 31
case 2:
if (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0){
day = 29
}else {
day = 28
}
default:
day = 30
}
fmt.Printf("%d年%d月共%d天",year,mouth,day)
}else{
fmt.Println("月份输入错误!!")
}
}
通过上面的案例,我们发现switch结构和if-else结构是可以结合来使用的,可以根据具体的问题具体分析,灵活来应用。
3.2 循环结构
3.2.1 循环概念
所谓的循环就是重复的做同一件事情,我们先从生活的角度来理解一下循环。
打印100份试卷
李四这次考试又粗心了,爸爸让他写1000遍“下次考试一定要细心”.
在编程中,我们也会经常遇到循环的问题,例如:
跟媳妇承认错误,说一万遍"媳妇儿,我错了"
fmt.Println(“媳妇儿,我错了”)
fmt.Println(“媳妇儿,我错了”)
fmt.Println(“媳妇儿,我错了”)
…………………………………
3.2.2 基本语法结构
在GO语言中,我们有专门实现这种循环的结构就是for结构(GO语言中只有for循环结构,没有while,do-while结构),基本语法结构如下:
for 表达式1;表达式2;表达式3{
循环体
}
表达式1:定义一个循环的变量,记录循环的次数
表达式2:一般为循环条件,循环多少次
表达式3:一般为改变循环条件的代码,使循环条件终有一天不再成立
循环体:重复要做的事情。
下面我们用for循环结构输出10遍“媳妇儿,我错了”。
func main() {
var i int
for i = 1;i <= 10;i++{
fmt.Println("媳妇儿,我错了")
}
}
以上代码执行的顺序:,
先执行表达式1,然后执行表达式2,判断循环条件是否成立,如果表达式2返回的结果为true,则执行循环体。当执行完循环体后,执行表达式3,然后执行表达式2(这时不会再执行表达式1)继续判断循环条件是否成立,如果成立则继续执行循环体,如果不成立,则跳出for循环。
我们也可以将语法进行简化如下:
func main() {
//var i int
for i := 1;i <= 10;i++{
fmt.Println("媳妇儿,我错了")
}
}
3.2.3 练习
(1)求1到100之间所有整数的和
func main() {
sum := 0
for i := 1;i <= 100;i++{
sum += i
}
fmt.Println(sum)
}
(2)求1到100之间所有偶数的和
func main() {
sum := 0
for i := 0;i <= 100;i+=2{
sum += i
}
fmt.Println(sum)
}
(3)敲7:计算1-100中 逢7 个位为7 十位为7 或7的倍数 需要敲桌子
func main() {
for i :=1;i <= 100;i++{
if i % 7 == 0 || i / 10 == 7 || i % 10 == 7 {
fmt.Println("敲桌子")
}else {
fmt.Println(i)
}
}
}
(4)找出100-999间的水仙花数(水仙花数指的就是 这个百位数字的,百位的立方+十位的立方+个位的立方==当前这个百位数字)
func main() {
var bw int //百位
var sw int //十位
var gw int //个位
for i := 100;i <= 999;i++{
bw = i / 100
sw = i / 10 % 10
gw = i % 10
if bw*bw*bw+sw*sw*sw+gw*gw*gw == i{
fmt.Println(i)
}
}
}
3.2.4 跳出语句
关于GO语句中的跳转语句,有break,continue,goto
下面我们先来讲解break
根据前面的案例,我们发现,循环必须指定循环条件,在满足循环条件的时候执行循环,如果不满足循环的条件,可以跳出整个循环。但是如果,我们没有指定循环条件,那么循环就成了死循环,所谓的死循环指的就是一直循环,跳不出来了。
怎样构建死循环呢?语法如下:
func main() {
for {
fmt.Println("hello")
}
}
死循环(无限循环)的语法非常简单,就是什么循环条件也没有写。
下面我们来看一下,关于死循环的应用场景
案例:要求用户输入用户名和密码,只要不是admin、888888就一直提示用户名,密码错误,请重新输入。
分析:该题我们怎样构建循环条件呢?
按照我们以前的做法,很难构建循环条件,那么我们可以使用死循环来做,但是,我们要在用户输入正确的用户名和密码的时候跳出整个循环,那么我们应该怎样强制的跳出死循环呢?我们可以使用break关键字。
break的作用就是强制结束当前循环,并开始执行循环之后的语句。
break 语句流程图如下:
案例演示如下:
func main() {
var username string
var passwd string
for {
fmt.Print("请输入用户名:")
fmt.Scanf("%s\n",&username)
fmt.Print("请输入密码:")
fmt.Scanf("%s",&passwd)
if username == "admin" && passwd == "888888"{
fmt.Println("登陆成功!")
//强制结束当前循环
break
}else {
fmt.Println("用户名或密码错误,请重新输入!")
}
}
}
通过以上案例演示,我们发现当程序执行到break语句时,会跳出for循环。
思考:现在将上面的题目的需求在改动一下,加上以下条件”用户名密码输入错误,最多输错3次,超过3次,提示输入错误信息次数太多,并且结束整个程序”,那么该程序怎样修改呢?
案例演示如下:
func main() {
var username string
var passwd string
var count int = 0
for {
fmt.Print("请输入用户名:")
fmt.Scanf("%s\n",&username)
fmt.Print("请输入密码:")
fmt.Scanf("%s",&passwd)
if username == "admin" && passwd == "888888"{
fmt.Println("登陆成功!")
//强制结束当前循环
break
}else {
count++
if count >= 3{
fmt.Println("出入错误次数太多!!")
break
}
fmt.Println("用户名或密码错误,请重新输入!")
}
}
}
continue语句
前面我们已经讲解完成了break,下面我们来说一下continue语句。
continue的作用是:立即结束本次循环,判断循环条件,如果成立,则进入下一次循环,否则退出循环。
基本语法:
func main() {
for i := 1;i <= 5;i++{
if i == 2{
continue
}
fmt.Println("i的值为:",i)
}
}
执行过程:当i的值为1时,判断循环条件,满足循环条件(i<=5),进入循环体,执行if判断,发现条件不满足,不执行continue,直接打印,第一次循环结束,进入第二次循环,这时变量i的值为2, 满足循环条件,进入循环体,执行if判断,发现满足条件,执行continue,continue的作用:结束本次循环,也就是不在执行后面的代码(不管后面有多少行代码都不在执行),直接跳转到for,执行for循环的第三个表达式,让i的值进行加1操作,这时i变量的值变成3,判断一下是否满足循环条件,满足(i<=5),进入循环体,开始执行,以此类推。最终输出结果:1,3,4,5
练习:用continue实现计算1到100(含)之间的除了能整除7之外所有整数的和
func main() {
sum := 0
for i := 1;i <= 100;i++{
if i % 7 == 0{
continue
}
sum += i
}
fmt.Println(sum)
}
最后是 goto
Go 语言的 goto 语句可以无条件地转移到过程中指定的行。
goto语句通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能。
但是,在结构化程序设计中一般不主张使用goto语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难。
示例如下:
func main() {
fmt.Println("helloworld1")
fmt.Println("helloworld2")
//这里的FLAG是自定义的,不是必须为FLAG
goto FLAG
fmt.Println("helloworld3")
fmt.Println("helloworld4")
FLAG:
fmt.Println("helloworld5")
fmt.Println("helloworld6")
}
结果如下:
helloworld1
helloworld2
helloworld5
helloworld6
3.2.5 嵌套循环
我们在前面学习选择结构时,讲解过关于选择结构的嵌套,同理循环结构也有嵌套。
基本使用结构如下:
func main() {
for i := 1;i <= 10;i++{
for j := 1;j <= 10;j++{
}
}
}
练习1:在屏幕上输出如下图所示的乘法口诀表
func main() {
for i := 1;i < 10;i++{
for j := 1;j < 10;j++{
fmt.Printf("%d*%d=%d\t",i,j,i*j)
}
fmt.Println()
}
}
练习2:输出以下结构的乘法口诀表
func main() {
for i := 1;i <10;i++{
for j := 1;j <=i;j++{
fmt.Printf("%d*%d=%d\t",i,j,i*j)
}
fmt.Println()
}
}
练习3:输出以下图形
*
***
*****
*******
*********
***********
func main() {
var num int
fmt.Print("你想输出几行:")
fmt.Scanf("%d\n",&num)
for i := 1;i <= num;i++{
for j := 1;j <= ((2*num-1)-(2*i-1))/2;j++ {
fmt.Print(" ")
}
for k := 1;k <=2*i-1;k++{
fmt.Print("*")
}
fmt.Println()
}
}
注意:尽量不要多层嵌套,性能比较低。