• 巨细靡遗流程控制,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang流程结构详解EP09


    流程结构就是指程序逻辑到底怎么执行,进而言之,程序执行逻辑的顺序。众所周知,程序整体都是自上由下执行的,但有的时候,又不仅仅是从上往下执行那么简单,大体上,Go lang程序的流程控制结构一共有三种:顺序结构,选择结构,循环结构。顺序结构:从上向下,逐行执行;选择结构:条件满足,某些代码才会执行,0-1次;循环结构:条件满足,某些代码会被反复的执行多次,0-N次

    选择结构之条件判断if/else

    市面上的语言都有if/else逻辑,逻辑非常简单,只要满足条件,就会执行条件代码块的逻辑:

    if 布尔表达式 {  
       /* 在布尔表达式为 true 时执行 */  
    }  
      
    if 布尔表达式 {  
       /* 在布尔表达式为 true 时执行 */  
    } else {  
      /* 在布尔表达式为 false 时执行 */  
    }  
      
    if 布尔表达式1 {  
       /* 在布尔表达式1为 true 时执行 */  
    } else if 布尔表达式2{  
       /* 在布尔表达式1为 false ,布尔表达式2为true时执行 */  
    } else{  
       /* 在上面两个布尔表达式都为false时,执行*/  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    具体逻辑:

    package main  
      
    import "fmt"  
      
    func main() {  
      
    	var a int = 1  
      
    	/* 使用 if 语句判断布尔表达式 */  
    	if a < 20 {  
    		/* 如果条件为 true 则执行以下语句 */  
    		fmt.Printf("a 小于 20\n")  
    	}  
    	fmt.Printf("a 的值为 : %d\n", a)  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    程序返回:

    a 小于 20  
    a 的值为 : 1
    
    • 1
    • 2

    需要注意的是,条件变量类型要一致才能比较。

    除此之外,if还可以在判断之前执行逻辑:

    package main  
      
    import (  
    	"fmt"  
    )  
      
    func main() {  
    	if num := 10; num%2 == 0 { //checks if number is even  
    		fmt.Println(num, "is even")  
    	} else {  
    		fmt.Println(num, "is odd")  
    	}  
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    程序返回:

    10 is even
    
    • 1

    也就是说,当判断变量num对2取余是否等于0之前,我们可以先给num进行赋值操作。

    同时if/else也支持多分支判断:

    
    
    package main  
      
    import (  
    	"fmt"  
    )  
      
    func main() {  
    	score := 88  
    	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 成绩不及格")  
    	}  
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    程序返回:

    成绩等级为B
    
    • 1

    这里程序根据变量的值而选择执行不同的分支代码,但需要注意的是,Go lang对于 { 和 } 的位置有严格的要求,它要求 else if (或 else ) 和两边的花括号,必须在同一行。即使在 { 和 } 之间只有一条语句,这两个花括号也是不能省略的。

    选择结构之选择判断switch

    switch关键字是一个条件语句,它计算表达式并将其与可能匹配的列表进行比较,并根据匹配执行代码块。它可以被理解为用一种普适的方式来写多个if else判断子句。

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

    说白了就是,每一个case都默认自动break,执行完了一个,switch逻辑也就结束了,不会顺序执行别的case,但是可以使用fallthrough强制执行后面的case代码:

    
    
    package main  
      
    import "fmt"  
      
    func main() {  
    	/* 定义局部变量 */  
    	var grade string = "B"  
    	var marks int = 40  
      
    	switch marks {  
    	case 90:  
    		grade = "A"  
    	case 80:  
    		grade = "B"  
    	case 50, 60, 70:  
    		grade = "C" //case 后可以由多个数值  
    	default:  
    		grade = "D"  
    	}  
      
    	switch {  
    	case grade == "A":  
    		fmt.Printf("A\n")  
    	case grade == "B", grade == "C":  
    		fmt.Printf("B\n")  
    	case grade == "D":  
    		fmt.Printf("D\n")  
    	case grade == "F":  
    		fmt.Printf("F\n")  
    	default:  
    		fmt.Printf("low\n")  
    	}  
    	fmt.Printf("你的等级是 %s\n", grade)  
    }  
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    程序返回:

    D  
    你的等级是 D
    
    • 1
    • 2

    这里我们先通过switch对marks变量进行值判断,在case分支里赋值grade变量,随后又在switch逻辑中对grade做恒等判断,然后输出。

    假设需要贯通后续的case,就添加fallthrough关键字:

    package main  
      
    import (  
    	"fmt"  
    )  
      
    func main() {  
    	switch x := 5; x {  
    	default:  
    		fmt.Println(x)  
    	case 5:  
    		x += 10  
    		fmt.Println(x)  
    		fallthrough  
    	case 6:  
    		x += 20  
    		fmt.Println(x)  
      
    	}  
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    这里首先进入case5逻辑,x经过运算后变为15,随后贯通进入下一个逻辑,x += 20 逻辑,变为35。

    程序返回:

    15  
    35
    
    • 1
    • 2

    需要注意的是,fallthrough应该是某个case的最后一行。如果它出现在中间的某个地方,编译器就会抛出错误。

    循环结构之遍历for

    for关键字可以用来重复执行某一段代码,在Python中,遍历方式有三种:for 、 while 和 do while 。但是Go lang只为我们提供了一种:for:

    package main  
      
    import (  
    	"fmt"  
    )  
      
    func main() {  
    	num := 1  
    	for num < 3 {  
    		fmt.Println(num)  
    		num++  
    	}  
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    程序返回:

    1  
    2
    
    • 1
    • 2

    这里是但条件循环,如果满足条件,for代码块的逻辑会重置执行。

    我们还可以为遍历添加额外的表达式逻辑,比如初始化控制变量,在整个循环生命周期内,只执行一次;设置循环控制条件,该表达式值为 true 时循环,值为 false 时结束循环;每次循环完都会执行此表达式,可以利用其让控制变量增量或减量:

    package main  
      
    import (  
    	"fmt"  
    )  
      
    func main() {  
    	for num := 0; num < 4; num++ {  
    		fmt.Println(num)  
    	}  
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    程序返回:

    0  
    1  
    2  
    3
    
    • 1
    • 2
    • 3
    • 4

    需要注意的是,在for关键字中声明的变量,也只在for的代码块中有效,因为和Python不同,go lang有严格的块作用域限制。

    在 Go lang中遍历一个可迭代的对象一般使用 for-range 语句实现,其中 range 后面可以接数组、切片、字符串等, range 会返回两个值,第一个是索引值,第二个是数据值:

    package main  
      
    import (  
    	"fmt"  
    )  
      
    func main() {  
      
    	str := "123456789"  
    	for index, value := range str {  
    		fmt.Printf("index %d, value %c\n", index, value)  
    	}  
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    程序返回:

    index 0, value 1  
    index 1, value 2  
    index 2, value 3  
    index 3, value 4  
    index 4, value 5  
    index 5, value 6  
    index 6, value 7  
    index 7, value 8  
    index 8, value 9
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如果for关键字后面没有表单式,就是死循环:

    package main  
      
    import (  
    	"fmt"  
    )  
      
    func main() {  
      
    	num := 1  
      
    	for {  
      
    		fmt.Println(num)  
    		num++  
      
    		if num > 3 {  
    			break  
    		}  
      
    	}  
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    程序返回:

    1  
    2  
    3
    
    • 1
    • 2
    • 3

    是的,我们当然可以使用break关键字来中断循环。

    但需要注意的是,break只能终端当前循环,不能终端外部循环:

    package main  
      
    import "fmt"  
      
    func main() {  
    	/* 定义局部变量 */  
    	var i, j int  
    	for i = 2; i < 10; i++ {  
    		for j = 2; j <= (i / j); j++ {  
    			if i%j == 0 {  
    				break // 如果发现因子,则不是素数  
    			}  
    		}  
    		if j > (i / j) {  
    			fmt.Printf("%d  是素数\n", i)  
    		}  
    	}  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    程序返回:

    2  是素数  
    3  是素数  
    5  是素数  
    7  是素数
    
    • 1
    • 2
    • 3
    • 4

    和Python一样,Go lang也具备continue关键字,continue 语句用来跳出 for 循环中的当前循环:

    package main  
      
    import "fmt"  
      
    func main() {  
      
    	for num := 1; num <= 10; num++ {  
    		if num%2 == 0 {  
    			continue  
    		}  
    		fmt.Println(num)  
    	}  
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    程序返回:

    1  
    3  
    5  
    7  
    9
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在 continue 语句后的所有的 for 循环语句都不会在本次循环中执行,执行完 continue 语句后将会继续执行一下次循环。这样我们就可以跳过偶数,直接打印出 10 以内的奇数。

    goto 无条件跳转

    使用goto关键字可以直接跳到下一步要执行的标签代码:

    package main  
      
    import "fmt"  
      
    func main() {  
      
    	for x := 0; x < 10; x++ {  
      
    		for y := 0; y < 10; y++ {  
      
    			if y == 2 {  
    				// 跳转到标签  
    				goto breakHere  
    			}  
      
    		}  
    	}  
      
    	// 手动返回, 避免执行进入标签  
    	return  
      
    	// 标签  
    breakHere:  
    	fmt.Println("done")  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    程序返回:

    done
    
    • 1

    需要注意的是,goto关键字与标签之间不能有变量声明,否则编译错误。

    结语

    和Python和Ruby相比,整体上,在流程结构控制环节,Go lang表现出了极大的克制,语法上删繁就简, 把动态语言那些桀骜不驯的语法糖压制成行文工整的诗,这样的好处是对初学者极为友好,没有太多规范需要记忆,大道至简,大巧不工。我们可以吐槽它没有while或者是do while,亦或者是lambda表达式等可以炫技的资本,但,那又如何呢?就像乔帮主在聚贤庄力战群雄,大杀四方,所倚重的不过是一套普普通通的太祖长拳,Go lang亦如此,务实胜过炫技,简单未必普通。

  • 相关阅读:
    Spring高手之路15——掌握Spring事件监听器的内部逻辑与实现
    学生身份标签的识别与风控应用
    dataV中重置边框组件的宽高的initWH方法的使用
    【Go语言入门】一文搞懂Go语言的最新依赖管理:go mod的使用
    【Spring面试】八、事务相关
    无公网IP与服务器完成企业微信网页应用开发远程调试详细流程
    炫酷3D按钮
    线性回归原理
    深度解读ChatGPT:揭开人工智能聊天机器人的神秘面纱
    对前端构建工具的一些理解
  • 原文地址:https://blog.csdn.net/zcxey2911/article/details/126307295