流程控制|使用循环结构等完成重复性工作(文末附视频)

news2024/11/15 15:29:42

本节介绍Go语言中的程序流程控制结构,具体包括以下内容:

  1. 循环结构
  2. 流程控制语句
  3. 条件分支结构

经过前面两个小节的学习,我们初步掌握了Go语言的语法知识。本小节将介绍循环和条件分支,从而使用少量代码完成大量重复性的操作,就像标准化作业一样。为了便于理解,本小节将使用3个示例来讲述具体的知识点。

循环结构

先来看这样一段输出:

可以看到,这是个由星号 * 组成的实心菱形,总共有13行。如何实现这样的效果呢?该不会是手写13行输出语句吧?当然不是!

💡 提示: 在实际开发中,产品的需求千变万化。面对复杂的功能,通常的做法是“拆分”。即把一个复杂的需求分解为多个简单的需求,然后逐个实现。

仔细观察上图中的输出内容可以发现,其实:

  • 菱形就是由若干行(总共13行)组成的;
  • 菱形是上下轴对称图形,以第7行为轴。

将菱形拆分为上下两个三角形,可以发现:

  • 每行都是由若干空格和若干星号构成;
  • 对于上半部分(i从1开始):
    • 第i行的星号数是2*i-1个;
    • 第i行的空格数是7-i个。
  • 对于下半部分(i从1开始):
    • 第i行的空格数是i个;
    • 第i行的星号数是2*7-1-(i*2)个。

到此,我们不仅做完了拆分,还摸透了规律。接下来,只要按规律编写代码即可。在Go语言中,像这种重复地执行相似逻辑,可以使用循环结构实现。循环结构的格式如下:

for init; condition; post {
    //循环体代码块
}

其中,for表明接下来的代码是for循环结构;init是初始化语句;condition是关系或逻辑表达式,值为true时则会停止循环;post是每次循环结束后执行的语句;循环体代码块就是要重复执行的代码了。

接下来,我们用这个循环结构实现上半部分的三角形:

func main() {
   n := 7
   for i := 1; i <= n; i++ {
      for j := 0; j < n-i; j++ {
         fmt.Print(" ")
      }
      for k := 0; k < 2*i-1; k++ {
         fmt.Print("*")
      }
      fmt.Println()
   }
}

执行结果为:

我们逐行理解上述代码。

  1. 声明变量n,并赋初值为7,表示上半部分由7行构成(包含对称轴)。
  2. 接下来是for循环结构,初始化条件是变量i为1,i表示总行数;判断退出循环的条件是变量i小于或等于n,即输出7行后退出;每次循环即完成单行输出,因此在循环后i自增1。如此,便构成了总共循环7次的for循环结构。
  3. 在for循环内部,有两个for循环,分别用于输出空格星号,另外在两个循环执行完毕后,输出了换行,用于折行。
  4. 用于输出空格的for循环结构,初始化条件是变量j为0,j表示输出的空格数;判断退出循环的条件是变量j小于n-i,即总共输出n-i个空格;每次循环完成所有空格的输出,因此循环后j自增1。如此,便实现了单行空格的输出。
  5. 用于输出星号的for循环结构,初始化条件是变量k为0,k表示输出的星号数;判断退出循环的条件是变量k小于2*i-1,即总共输出2*i-1个星号;每次循环完成所有星号的输出,因此循环后k自增1。如此,便实现了单行星号的输出。

好了,如果各位理解了上半部分的实现原理,不妨亲自动手尝试实现下半部分。

❗️ 注意: 使用循环时,务必确保有明确的可退出循环的条件,否则程序将陷入死循环,无法终止。在开发时,若不慎执行了死循环,可点击GoLand工具栏中的“Stop”按钮(接近红色,有点像音乐播放器的停止播放按钮)强行停止。

输出菱形的完整代码如下:

func main() {
    n := 7
    for i := 1; i <= n; i++ {
	for j := 0; j < n-i; j++ {
		fmt.Print(" ")
	}
	for k := 0; k < 2*i-1; k++ {
		fmt.Print("*")
	}
	fmt.Println()
    }
    for i := 1; i < n; i++ {
	for j := 0; j < i; j++ {
            fmt.Print(" ")
	}
	for k := 0; k < 2*n-1-2*i; k++ {
            fmt.Print("*")
	}
            fmt.Println()
    }
}

条件分支结构

接下来,输出菱形的题目要“升级了”!

单纯地输出菱形未免太单调了些,我们希望通过不同的文字来输出不同的样式。当文字为“上”的时候,输出上半截7行三角形;当文字为“下”时,输出下半截6行三角形;当文字为“全”是,输出13行菱形。

显然,这个题目升级需要进行“条件判断”,不同的条件执行不同的逻辑。如果Go语言能有“如果……那么……”这种结构就好了!Go语言恰恰有这种结构——条件分支。

Go语言中的条件分支结构如下:

if condition {
    //条件成立时要执行的语句
}else{
    //条件不成立时要执行的语句
}

其中,condition是关系或逻辑表达式。另外,如无必要,else是可以省略的:

if condition {
    //条件成立时要执行的语句
}

如有必要,还可追加更多的判断条件:

if condition1 {
    //条件condition1成立时要执行的语句
}else if condition2 {
    //条件condition2成立时要执行的语句
}else if condition3 {
    //条件condition3成立时要执行的语句
}else{
    //以上三种条件都不成立时要执行的语句
}

如此,解答“升级”后的题目就容易多了。参考条件分支的结构,思路如下:

if 文字是“上”或“全”{
    输出菱形前7行
}
if 文字是“下”或“全”{
    输出菱形后6行
}

之前我们已经完成了输出菱形,只需将新的代码逻辑与之结合即可,完整代码如下:

func main() {
   outputMode := "全"

   n := 7
   if outputMode == "上" || outputMode == "全" {
      for i := 1; i <= n; i++ {
         for j := 0; j < n-i; j++ {
            fmt.Print(" ")
         }
         for k := 0; k < 2*i-1; k++ {
            fmt.Print("*")
         }
         fmt.Println()
      }
   }
   if outputMode == "下" || outputMode == "全" {
      for i := 1; i < n; i++ {
         for j := 0; j < i; j++ {
            fmt.Print(" ")
         }
         for k := 0; k < 2*n-1-2*i; k++ {
            fmt.Print("*")
         }
         fmt.Println()
      }
   }
}

我们可以通过改变outputMode的值来控制输出的文字形状。

流程控制语句

流程控制语句多用于管理循环结构的运行。考虑这样一个需求:编程实现查找1-10以内的素数。

💡 提示: 素数又称质数,是指在大于1的自然数中,除了1和它本身以外不能被其它整数整除的自然数,2是最小的素数。

这一次,我们需要在已有的代码上增加,但不改变原有的代码。先来看看现有代码:

func main() {
    for i := 2; i > 0; i++ {
	if i == 2 {
            fmt.Println(i)
	}
	//假定i为素数
	flag := true
	for j := 2; j < i; j++ {
            if i%j == 0 {
		//当i能被某个整数整除时,不是素数
		flag = false
            }
	}
	//如果依旧为true,则i为素数
	if flag {
            fmt.Println(i)
	}
    }
}

通过阅读上述代码可以发现:

  • 代码整体由一个for循环构成,初始化语句声明了变量i,从2开始(2是最小的素数),循环结束的条件是i大于0,每次循环结束后i自增1;
  • 循环体内,首先判断了i是否等于2,如果是的话直接输出了i的值;
  • 然后,声明了布尔类型变量flag,表明是否为素数,用于后续判断是否输出i的值;
  • 接下来,使用循环结构判断i是否为素数。初始化时声明了变量j,从2开始,跳出循环的条件时j小于i,判断i是否为素数只需从2开始尝试做除法,直到i-1为止。若余数为0,则表示能被整除,此时,flag应改为false。每次循环结束后j自增1;
  • 最后,判断flag的值,若flag为true,则表示i是素数,输出i,反之则不是素数。

代码运行后,控制台输出:

2
2
3
5
7
11
13
...

明明是查找10以内的素数,为何不停地输出这么多结果呢?请大家来找茬,看看这段代码中有哪些问题?

  1. 最外层的for循环,终止条件是i大于0,但i始终是大于0的,程序一旦开始,便无法结束,陷入死循环;
  2. 当i等于2时,输出了一次i的值。然而在内层的循环体中,还将再次输出。最终将输出两次2;
  3. 在内层循环中,一旦i与j取余结果为0,则表明i不是素数,内层for循环结构无需再执行剩下的循环了。

解决了这3个问题,便能实现查找1-10以内的素数的需求了。要解决它们,就需要请出Go语言中的流程控制语句来“救场”了。在Go语言中,较为常用的流程控制语句有continuebreak。前者的意义是立即结束本次循环,执行下一个循环;后者的意义是终止循环。

显然,解决问题1和3,只需使用break语句打断相应循环的执行即可;解决问题2,只需使用continue语句提前终止本次循环,直接执行下一次循环即可。因此,将代码改为:

func main() {
    for i := 2; i > 0; i++ {
        //当i大于10s
        if i > 10 {
            break
	}
	if i == 2 {
            fmt.Println(i)
            continue
	}
	//假定i为素数
	flag := true
	for j := 2; j < i; j++ {
            if i%j == 0 {
                //当i能被某个整数整除时,不是素数
		flag = false
		break
            }
	}
	//如果依旧为true,则i为素数
	if flag {
            fmt.Println(i)
	}
    }
}

运行结果为:

2
3
5
7

小结

🎉 恭喜,您完成了本次课程的学习!

📌 以下是本次课程的重点内容总结:

  1. 循环结构
  2. 流程控制语句
  3. 条件分支结构

在实际开发中,代码流程控制可以帮助我们使用较少的代码完成大量重复性的工作。除了本讲中提及的常用流程控制结构外,还有用于条件分支的Switch...case...结构、用于流程控制的goto语句,感兴趣的朋友可以当作扩展阅读。

➡️ 在下次课程中,我会介绍如下内容:

  • Go语言中的数组、切片和集合的声明和赋值

零基础通关 Go 语言 - 萧文翰 - 掘金小册2大部分,10大技能,全解Go语言语法。「零基础通关 Go 语言」由萧文翰撰写,950人购买https://s.juejin.cn/ds/kqXRu6Y/

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

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

相关文章

NestJS 项目实战 需求分析(文末附视频)

前言 一般常规的项目立项之初会有一份 MRD&#xff08;Market Requirements Document&#xff0c;市场需求文档&#xff09;用来判断产品的必需性以及价值等。 对于基础项目开发来说&#xff0c;使用 MRD 可能有些重量级&#xff0c;但我们也需要对一个新的基建类型项目做一个…

【快速幂】875. 快速幂

875. 快速幂 文章目录题目描述输入格式&#xff1a;输出格式&#xff1a;数据范围输入样例输出样例方法&#xff1a;快速幂解题思路代码复杂度分析&#xff1a;题目描述 给定 nnn 组 ai,bi,pia_i,b_i,p_iai​,bi​,pi​&#xff0c;对于每组数据&#xff0c;求出 aibimodpia_i…

Numpy常用random随机函数

Numpy常用random随机函数 seed 向随机数生成器传递随机状态种子 只要random.seed( * ) seed里面的值一样&#xff0c;那随机出来的结果就一样。所以说&#xff0c;seed的作用是让随机结果可重现。也就是说当我们设置相同的seed&#xff0c;每次生成的 随机数相同。如果不设置…

冯 • 诺依曼体系结构与操作系统

目录 一、冯 • 诺依曼体系结构 1.1 冯 • 诺依曼体系结构推导 1.2 内存提高效率 1.3 具体案例理解冯 • 诺依曼体系结构 1.4 其他认识 二、操作系统 2.1 操作系统概念 2.2 操作系统的上下层 2.3 管理理念:先描述&#xff0c;再组织 一、冯 • 诺依曼体系结构 1.1 冯 …

Acwing - 算法基础课 - 笔记(数学知识 · 四)(补)

数学知识&#xff08;四&#xff09; 这一小节讲的是容斥原理和简单博弈论。 容斥原理 定义 最基本的&#xff0c;假设有3个两两相交的圆。那么三个圆所覆盖的面积大小为 S1S2S3−S1∩S2−S2∩S3−S1∩S3S1∩S2∩S3S_1S_2S_3 - S_1 \cap S_2 - S_2 \cap S_3 - S_1 \cap S_3…

【JavaEE】如何开始最基础的Servlet编程(借助Tomcat实现)

什么是Servlet我们知道服务器工作的三部曲&#xff1a;接收请求 -> 处理请求并计算响应 -> 发送响应Servlet是个接口&#xff0c;实现这个接口的类就是用来进行中间的一个步骤“处理请求并计算响应的”&#xff0c;应用于HTTP传输的中间层。借助Tomcat服务器进行Servlet编…

【论文速递】WACV2022 - 从边界框标注学习小样本分割

【论文速递】WACV2022 - 从边界框标注学习小样本分割 【论文原文】&#xff1a;Learning Few-shot Segmentation from Bounding Box Annotations 获取地址&#xff1a;https://openaccess.thecvf.com/content/WACV2023/papers/Han_Learning_Few-Shot_Segmentation_From_Bound…

Word文档和PDF文件如何互相转换?

工作中&#xff0c;有时候我们需要把Word转换成PDF格式&#xff0c;转换后不但更美观、专业&#xff0c;也可以防止文档被修改。 那Word文档如何转换成PDF文件呢&#xff1f;其实在Word里面就可以直接转换。 文档编辑好后&#xff0c;在菜单中点击【文件】选项&#xff0c;然…

搭建 Go 语言的开发环境(文末附视频讲解)

从本小节开始&#xff0c;我们就要正式动手实践了。 类比现实生活&#xff0c;我们若要钉钉子&#xff0c;就需要准备锤子&#xff1b;想要烧菜&#xff0c;就需要准备灶具和食材…… 类似地&#xff0c;若要在电脑上编写 Go 语言程序&#xff0c;便要先配置开发环境。 下载和…

干货 | 互联网广告数据的匿名化方案研究

以下内容整理自清华大学《数智安全与标准化》课程大作业期末报告同学的汇报内容。第一部分&#xff1a;背景介绍一、匿名化必要性互联网广告具有非常重要的商业价值&#xff0c;同时也是涉及数据处理十分密集的行业&#xff0c;出现了操作规范化、个人信息保护和商业数据安全等…

[GXYCTF2019]禁止套娃(无参数RCE)

目录 信息收集 知识讲解 涉及函数 PHP的正则表达式 无参rce 用到的函数 思路分析 方法一 方法二 信息收集 拿到这道题&#xff0c;抓包看了看&#xff0c;啥也没有&#xff0c;用dirsearch爆破目录发现.git目录&#xff0c;猜测存在.git源码泄露&#xff0c;用githac…

Web Spider XHR断点 堆栈跟值 逆向案例(四)

声明 此次案例只为学习交流使用&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;切勿用于其他非法用途&#xff1b; 文章目录声明前言一、任务说明二、网站分析三、XHR断点调试&#xff0c;扣JS加密代码四、代码实现1、JS加密代码&#xff1a;encode.js2、…

安卓逆向:基础入门(一)

前言随着app的广泛应用&#xff0c;使用过程中&#xff0c;难免会遇到些很不友好的功能&#xff0c;比如&#xff1a;游戏充值、间断性弹窗广告、续费解锁下一回等等。而随之会产生如何将这些功能取消掉&#xff0c;而Android逆向就可以做到&#xff0c;纵向丝滑。当然这只是安…

Kinect与TOF、双目、结构光相机比较相机国产、非国产统计参数对比分析

Kinect与TOF、双目、结构光相机比较相机国产、非国产统计参数对比分析 Kinect v1和Kinect v2之间的参数比较 从图中可以看出&#xff0c;Kinect v2的表现比Kinect v1要好得多&#xff1a;首先最令人印象深刻的是分辨率的提高&#xff0c;v2达到了1080p&#xff0c;甚至视野也大…

JavaWeb | JDBC概述及IDEA连接MySQL

本专栏主要是记录学习完JavaSE后学习JavaWeb部分的一些知识点总结以及遇到的一些问题等&#xff0c;如果刚开始学习Java的小伙伴可以点击下方连接查看专栏 本专栏地址&#xff1a;&#x1f525;JavaWeb Java入门篇&#xff1a; &#x1f525;Java基础学习篇 文章目录一、前言二…

java基础学习 day36(字符串相关类的底层原理)

字符串存储的内存原理 直接赋值会复用字符串常量池中已有的new出来的不会复用&#xff0c;而是开辟一个新的空间来创建 “”号比较的到底是什么 基本数据类型比较数据值引用数据类型比较地址值 PS. 所以以后对引用数据类型&#xff0c;不要用“”&#xff0c;改用.equals()…

RS485接线方式小科普

欢迎来到东用知识小课堂&#xff01;RS-485采用平衡发送和差分接收方式实现通信&#xff1a;发送端将串行口的ttl电平信号转换成差分信号a&#xff0c;b两路输出&#xff0c;经过线缆传输之后在接收端将差分信号还原成ttl电平信号。RS-485总线网络拓扑一般采用终端匹配的总线型…

【Linux】基于 Pintos 实现新的用户级程序的系统调用 | 冯诺依曼架构

&#x1f4ad; 写在前面&#xff1a;本章我们首先会明确冯诺依曼体系结构的概念&#xff0c;旨在帮助大家理解体系结构在硬件角度去理解数据流走向的问题。理解完之后我们再去谈操作系统&#xff0c;这个在之前的章节已经有所铺垫&#xff0c;当时我们只讲解了操作系统是什么&a…

车载以太网 - 车辆信息和车辆声明 - 09

到今天这一篇,对于ISO 13400 - 2的DoIP协议介绍就完事了,对DoIP协议的规范介绍基本已经全部包括了,无论是我们作为软件开发人员还是测试人员,了解这部分内容基本就能够满足这块基础的开发要求,大家如果在研究或者学习这块内容的时候有什么问题欢迎私聊;并且在本篇文章结束…

Nginx使用(四)动静分离实例

一、简介Nginx动静分离简单来说就是把动态跟静态请求分开&#xff0c;不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求和静态请求分开&#xff0c;可以理解成使用Nginx处理静态页面&#xff0c;Tomcat处理动态页面&#xff0c;动静分离从目前实…