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

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    本节介绍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为1i表示总行数判断退出循环的条件是变量i小于或等于n即输出7行后退出每次循环即完成单行输出因此在循环后i自增1。如此便构成了总共循环7次的for循环结构。
    3. 在for循环内部有两个for循环分别用于输出空格星号另外在两个循环执行完毕后输出了换行用于折行。
    4. 用于输出空格的for循环结构初始化条件是变量j为0j表示输出的空格数判断退出循环的条件是变量j小于n-i即总共输出n-i个空格每次循环完成所有空格的输出因此循环后j自增1。如此便实现了单行空格的输出。
    5. 用于输出星号的for循环结构初始化条件是变量k为0k表示输出的星号数判断退出循环的条件是变量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/

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6