Golang语言流程控制之for循环结构篇

                                              作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一. for循环

1 for循环基本写法

Go语言中的所有循环类型均可以使用for关键字来完成,换句话说,Go语言并不支持"while","do...while"类似的写法。

for循环的基本格式如下:
    for 初始表达式;布尔表达式;迭代因子{
        循环体语句
    }

for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构。

for循环在第一次反复之前要进行初始化,即初始化表达式,随后,对布尔表达式进行判定,若判定结果为true,则执行循环体,否则,终止循环;随后在某一次反复的时候,进行某种形式的"步进",即执行迭代因子。
	- 1.初始表达式设置循环变量的初值;
	- 2.条件判断部分为任意布尔表达式;
	- 3.迭代因子控制循环变量的增减;
	
for循环在执行条件判定后,先执行的循环体部分,再执行步进。

无限循环(也称为"死循环")基本格式如下:
    for {
        循环体语句
    }
    
for循环可以通过break、goto、return、panic语句强制退出循环。

Go语言中可以使用for range遍历数组、切片、字符串、map及通道(channel),其返回值有以下规律:
	(1)数组、切片、字符串返回索引和值。
	(2)map返回键和值。
	(3)通道(channel)只返回通道内的值。
	
温馨提示:
	- 1.for循环的初始化表达式,不能用var定义变量的形式,要用":=";
	- 2.for循环作用就是让程序员写代码的效率提高了(说白了,只是让程序员写代码简洁而已),但是底层该怎么执行还是怎么执行的,底层效率没有任何提高;

2 for循环引入

package main

import "fmt"

func main() {
	// 实现一个功能,求和: 1,3,5,7,9

	// 实现方式一: 变量定义太多啦!
	var (
		a    int = 1
		b        = 3
		c        = 5
		d        = 7
		e        = 9
		sum1     = 0
	)

	sum1 += a
	sum1 += b
	sum1 += c
	sum1 += d
	sum1 += e

	fmt.Printf("sum1 = %d\n", sum1)

	// 实现方式二: 重复代码过多
	var (
		i    int = 1
		sum2     = 0
	)

	sum2 += i
	i += 2

	sum2 += i
	i += 2

	sum2 += i
	i += 2

	sum2 += i
	i += 2

	sum2 += i
	fmt.Printf("sum2 = %d\n", sum2)

	// 实现方式三: 利用for循环解决问题
	var sum3 int = 0

	for x := 1; x <= 9; x += 2 {
		sum3 += x
	}

	fmt.Printf("sum3 = %d\n", sum3)

	/*
		温馨提示:
			- 1.for循环的初始化表达式,不能用var定义变量的形式,要用":=";
			- 2.for循环作用就是让程序员写代码的效率提高了(说白了,只是让程序员写代码简洁而已),但是底层该怎么执行还是怎么执行的,底层效率没有任何提高;
	*/

	// for循环的变种写法,for循环语法非常灵活。
	var (
		sum4 int = 0
		y        = 1 // 变量的初始化
	)

	for y <= 9 { // 条件表达式,判断条件
		sum4 += y // 循环体
		y += 2    // 迭代因子
	}

	fmt.Printf("sum4 = %d\n", sum4)

	// x变量无法访问,但是y变量可以被访问。
	// fmt.Printf("x = %d\n", x)
	fmt.Printf("y = %d\n", y)
}

3.for循环原理

如上图所示,是for循环的执行顺序图解。

在经历5次循环之后,该进行第6次循环时i的值变为11,然后11不满足i<=9的条件,返回结果为false,因此不再执行循环体的代码,因此最终sum3的结果为25。

4.for死循环案例

package main

import (
	"fmt"
	"time"
)

func main() {
	var count int64 = 0

	// 死循环
	for {
		time.Sleep(1 * time.Second) // 每次睡眠1秒钟,用于模拟打游戏的时间!

		count++
		
		fmt.Printf("第【%d】次复活\n", count)
		if count == 3 {
			fmt.Println("闯关失败,即将重新开始闯关!")
			count = 0
		}
	}
}

二 .for range键值循环案例

1 for range概述

for range结构是GO语言特有的一种迭代结构,在许多情况下都非常有用。

for range可以遍历数组,切片,字符串,map及channel。for range语法上类似于其他语言中的foreach语句。

2 for range遍历字符串

package main

import (
	"fmt"
)

func main() {
	// 暂时先不要用中文测试,因为对于方式一的遍历有影响,对于方式二的没有影响
	// teacher := "JasonYin2020"
	teacher := "JasonYin2020尹正杰"

	// 方式一: 普通for循环,按照字节进行遍历输出的,如果想要使用这种方式遍历汉字,等学完切片再处理不迟。
	// for index := 0; index < len(teacher); index++ {
	// 	fmt.Printf("第【%d】个字符是: %c\n", index+1, teacher[index])
	// }

	// 方式二: 对teacher进行遍历,遍历的每个结果的索引值被k接受,每个结果的具体数值被v接受。
	for k, v := range teacher {
		fmt.Printf("第【%d】个字符是: %c\n", k, v)
	}
}

三.break关键字

1.break作用

- 1.switch分支中,每个case分支后都有break结束当前分支,但是在Go语言中break可以省略不写;;

- 2.break可以结束正在执行的for循环;

- 3.break的作用结束离他最近的循环;

2 break跳出循环

package main

import (
	"fmt"
)

func main() {
	var (
		age   uint8
		myAge uint8 = 29
	)

	for {
		fmt.Print("请猜测我的年龄,输入数字即可:>>> ")
		fmt.Scanln(&age)

		if age < myAge {
			fmt.Println("猜小了...")
		} else if age > myAge {
			fmt.Println("猜大了...")
		} else {
			fmt.Printf("恭喜您,猜对啦,我的年龄是: %d,你是一个好人!\n", myAge)
			// break可以结束正在执行的for循环
			break
		}
	}

	fmt.Println("猜年龄程序运行结束,欢迎下次使用~")
}

3.break退出嵌套for循环

package main

import "fmt"

func main() {
	for i := 1; i <= 3; i++ {
		for j := 7; j <= 9; j++ {
			fmt.Printf("i: %d, j:%d \n", i, j)
			if i == 2 && j == 8 {
				// 此处break的作用就是结束离它最近的for循环。
				break
			}
		}
	}

	fmt.Println("程序运行结束啦......")
}

4 break退出指定的标签

package main

import "fmt"

func main() {

	/*
		温馨提示:
			1.一旦定义标签,则必须在后续的代码中引用标签,否则就会抛出异常:  label <LABEL_NAME> defined and not used
			2.本案例的"haha"标签其实是可以不定义的,因为break默认就是退出最近一层的for循环哟;此处我故意这样写你为了加深大家的理解;

	*/

xixi: // 定义一个名为"xixi"的标签
	for i := 1; i <= 5; i++ {
	haha: // 定义一个名为"haha"的标签
		for j := 7; j <= 9; j++ {
			fmt.Printf("i: %d, j:%d \n", i, j)
			if i == 1 && j == 8 {
				// 结束指定标签对应的循环
				break haha
			}
			if i == 3 && j == 8 {
				// 结束指定标签对应的循环
				break xixi
			}
		}
	}

	fmt.Println("程序运行结束啦......")
}

四.continue关键字

1 continue作用

- 1.结束本次循环,继续下一次循环;

- 2.

2 continue结束本次循环

package main

import (
	"fmt"
)

func main() {

	var (
		number int = 0
	)

	fmt.Print("请输入一个范围以便于显示7的倍数:>>> ")
	fmt.Scanln(&number)

	for i := 0; i < number; i++ {
		if i%7 != 0 {
			// 结束本次循环,继续下一次循环
			continue
		} else {
			fmt.Printf("【%d】是7的倍数\n", i)
		}
	}

	fmt.Println("数7游戏运行结束啦......")
}

3 continue结束嵌套for循环

package main

import "fmt"

func main() {
	for i := 1; i <= 3; i++ {
		for j := 7; j <= 9; j++ {

			if i == 2 && j == 8 {
				// 此处continue的作用就是结束本次离它最近的for循环,然后继续下一次离它最近的for循环
				continue
			}

			fmt.Printf("i: %d, j:%d \n", i, j)
		}
	}

	fmt.Println("程序运行结束啦......")

}

4 continue结束指定的标签

package main

import "fmt"

func main() {

	/*
		温馨提示:
			1.一旦定义标签,则必须在后续的代码中引用标签,否则就会抛出异常:  label <LABEL_NAME> defined and not used
			2.本案例的"haha"标签其实是可以不定义的,因为continue默认就是跳出最近一层的for循环哟;此处我故意这样写你为了加深大家的理解;

	*/

xixi: // 定义一个名为"xixi"的标签
	for i := 1; i <= 5; i++ {
	haha: // 定义一个名为"haha"的标签
		for j := 7; j <= 9; j++ {

			if i == 1 && j == 8 {
				// 结束指定标签对应的循环
				continue haha
			}
			if i == 3 && j == 8 {
				// 结束指定标签对应的循环
				continue xixi
			}

			fmt.Printf("i: %d, j:%d \n", i, j)
		}
	}

	fmt.Println("程序运行结束啦......")
}

五.goto关键字

1 goto概述

Golang中的goto语句通过标签进行代码间的无条件跳转。

goto语句通常与条件语句配合使用,可用来实现条件转移,goto语句可以在快速跳出循环、避免重复退出上有一定的帮助。

Go语言中使用goto语句能简化一些代码的实现过程。 


温馨提示:
	1.goto在汇编语言使用较多,在高级语言中使用较少;
	2.在Go程序设计中一般不建议使用goto语句,以免造成程序流程的混乱。

2 goto测试样例

package main

import "fmt"

func main() {

	var (
		a int = 10
		b     = 5
	)

	fmt.Println("hello golang1")
	fmt.Println("hello golang2")
	if a > b {
		// goto一般配合条件结构一起使用,跳转到指定标签
		goto xixi
	}
	fmt.Println("hello golang3")
	fmt.Println("hello golang4")
	fmt.Println("hello golang5")
	fmt.Println("hello golang6")
	fmt.Println("hello golang7")
xixi:
	fmt.Println("hello golang8")
	fmt.Println("hello golang9")

}

3 goto跳转到指定标签

package main

import (
	"fmt"
)

func main() {

	// 在不使用goto指令时,定义一个标志位,用来判断是否结束外层嵌套for循环。
	flag := false

	for i := 1; i < 5; i++ {
		for j := 7; j < 9; j++ {
			if i == 2 && j == 8 {
				flag = true
				break
			}
			fmt.Printf("%d -- %d \n", i, j)
		}
		// 通过标志位来判断是否跳出外层for循环
		if flag {
			break
		}
	}
	fmt.Printf("通过标志位[flag = %t]退出,嵌套for循环结束啦....\n", flag)

	for i := 1; i < 5; i++ {
		for j := 7; j < 9; j++ {
			if i == 2 && j == 8 {
				goto haha
			}
			fmt.Printf("%d -- %d \n", i, j)
		}

	}

	// 定义一个标签名为"haha"(该名称可以自定义哟),标签需要被引用否则会报错
	// 实际工作中,尽量少用goto指令,尽管它看上去比上面使用flag的方式语法更简洁,但用的多容易混乱哟!
haha:
	fmt.Println("程序运行结束,嵌套for循环结束啦....")

}

六.return关键字

1 return概述

return用于直接结束当前函数,不在继续往后执行代码。

2 return测试样例

package main

import "fmt"

func main() {

	for i := 1; i <= 100; i++ {
		fmt.Printf("当前是第[%d]次循环\n", i)

		if i == 5 {
			// 直接结束当前函数,不在继续往后执行代码
			return
		}
	}

	// 由于上面已经return了,因此本行代码是不会被执行的哟~
	fmt.Println("程序运行结束")
}

七.练习题

1.计算100以内的偶数的和

package main

import (
	"fmt"
)

func main() {
	// 计算100以内的偶数的和
	for number := 0; number <= 100; number++ {
		if number%2 == 0 {
			fmt.Printf("【%d】是偶数\n", number)
		}
	}
}

2.统计300-500以内的所有素数

package main

import (
	"fmt"
)

func main() {
	// 素数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数

	// 统计素数的个数
	var count int = 0

	for i := 300; i < 500; i++ {

		// 定义标志位,如果找到了素数,则为true,默认我们就认为本次循环找到了素数
		flag := true

		// 判断i是否为素数
		for j := 2; j < i; j++ {
			if i%j == 0 {
				flag = false
				break
			}
		}
		// 打印素数
		if flag {
			count++
			// fmt.Printf("%d是素数\n", i)
		}
	}

	fmt.Printf("300-500以内,共计有[%d]个素数!", count)
}

3.编写代码打印99乘法表

package main

import (
	"fmt"
)

func main() {
	for i := 1; i <= 9; i++ {
		for j := 1; j <= i; j++ {
			fmt.Printf("%d x %d = %d\t", j, i, i*j)
		}
		fmt.Println()
	}
}
posted @ 2024-07-10 05:56  尹正杰  阅读(29)  评论(0编辑  收藏  举报