goland - 流程控制

x33g5p2x  于2022-08-17 转载在 其他  
字(7.2k)|赞(0)|评价(0)|浏览(561)

分类

顺序控制

图解

分支控制

单分支控制语句

语法结构

流程图解

双分支控制语句

基本语法

图解

多分支控制语句

基本语法

流程图

嵌套分支语句

switch分支控制

switch 的流程图

switch的使用的注意事项和细节

switch和if的比较

循环控制

for循环

语法格式

格式说明

执行顺序

流程图

使用细节

while和 do..while的实现

while循环的实现

do..while的实现

多重循环控制

跳转控制语句-break

使用细节和注意事项

跳转控制语句-continue

跳转控制语句-goto

跳转控制语句-return

defer - 延时机制

defer的最佳实践

分类

1)顺序控制

2)分支控制

3)循环控制

顺序控制

  1. 程序从上到下逐行地执行,中间没有任何判断和跳转。
  2. 没有判断,也没有跳转.因此程序按照默认的流程执行,即顺序控制。

 图解

分支控制

单分支控制语句

语法结构

if  条件表达式 {
    执行代码块
}

当条件表达式为ture时,就会执行的代码。注意是必须有的,就算你只写一行代码

golang支持在if中,直接定义一个变量

var age int
fmt.Print("请输入你的年龄:")
fmt.Scanln(&age)
if name := "张三";age > 18 {
   fmt.Printf("%v你年龄大于18,可以玩游戏",name)
} else {
   fmt.Printf("%v你年龄不大,不可以玩游戏",name)
}

 流程图解

 双分支控制语句

基本语法

if 条件表达式 {
    执行代码块1
}else {
    执行代码块2
}

当条件表达式成立,即执行代码块1,否则执行代码块2

package main

import "fmt"

func main() {
	var age uint
	fmt.Print("请输入你的年龄:")
	fmt.Scanln(&age)
	if age > 18 {
		fmt.Println("你的年龄大于18可以上网")
	}else {
		fmt.Println("你还未成年不可以上网")
	}
}

图解


 

1)从上图看条件表达式就是  age >18

2)执行代码块1 ==> fmt.Println("你的年龄大于18可以上网")

3)执行代码块2 ==> fmt.Println("你还未成年不可以上网")

4)强调一下双分支只会执行其中的一个分支。

多分支控制语句

基本语法

if 条件表达式1 {
    执行代码块1
} else if条件表达式2 {
    执行代码块2
}
 .....
} else {
    执行代码块n
}

1)多分支的判断流程如下:

(1)先判断条件表达式1是否成立,如果为真,就执行代码块1

(2)如果条件表达式1如果为假,就去判断条件表达式2是否成立,如果条件表达式2为真,就执行代码块2

(3)依次类推.

(4)如果所有的条件表达式不成立,则执行else的语句块。

2)else不是必须的。

3)多分支只能有一个执行入口

流程图

 嵌套分支语句

在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支外面的分支结构称为外层分支。

if 条件表达式 {
    执行代码块
    if 条件表达式 {    
        执行代码块
    }else {
            执行代码块
           }
}

嵌套分支不宜过多,建议控制在3层内

 switch分支控制

  1. switch 语句用于基于不同条件执行不同动作,每一个case分支都是唯一的,从上到下逐一测试,直到匹配为止。

2)匹配项后面也不需要再加 break

switch 表达式 {
case 表达式1,表达式2,...:
    语句块
case 表达式3,表达式4,...:
    语句块
.....
default:
    语句块
}

switch 的流程图

1)switch的执行的流程是,先执行表达式,得到值,然后和 case的表达式进行比较,如果相等,就匹配到,然后执行对应的case 的语句块,然后退出switch控制。

2)如果switch的表达式的值没有和任何的case 的表达式匹配成功,则执行default 的语句块。执行后退出switch 的控制.

3)golang 的case后的表达式可以有多个,使用逗号间隔.

4)golang 中的case 语句块不需要写break ,因为默认会有,即在默认情况下,当程序执行完case语句块后,就直接退出该switch控制结构。

var day string
fmt.Print("请输入:")
fmt.Scanln(&day)

switch day {
case "星期一":
   fmt.Println("星期一")
case "星期二":
   fmt.Println("星期二")
case "星期三":
   fmt.Println("星期三")
case "星期四":
   fmt.Println("星期四")
case "星期五":
   fmt.Println("星期五")
default:
   fmt.Println("周末")
}

 switch的使用的注意事项和细节

1)case/switch后是一个表达式(即:常量值、变量、一个有返回值的函数等都可以)

func test(key byte) byte {
	return key
}

func main() {
	var strCHar byte = 'a'
	switch test(strCHar) + 1 {
	case 'a':
		fmt.Println("a")
	case 'b':
		fmt.Println('b')
	case 'c':
		fmt.Println('c')
	default:
		fmt.Printf("%c",test(strCHar) + 1)
	}
}

2)case后的各个表达式的值的数据类型,必须和 switch 的表达式数据类型一致

3)case后面可以带多个表达式,使用逗号间隔。比如 case表达式1,表达式2 ...

4)case后面的表达式如果是常量值(字面量),则要求不能重复

5)case后面不需要带 break,程序匹配到一个case后就会执行对应的代码块,然后退出 switch,如果一个都匹配不到,则执行default

6)default语句不是必须的.

7)switch后也可以不带表达式,类似if --else分支来使用。

func main() {
	age := 20
	switch {
	case age == 10:
		fmt.Println("age == 10")
	case age == 20:
		fmt.Println("age == 20")
	default:
		fmt.Println("age == ",age)
	}
}
  1. switch 后也可以直接声明/定义一个变量,分号结束,不推荐
switch age := 20;{
	case age == 10:
		fmt.Println("age == 10")
	case age == 20:
		fmt.Println("age == 20")
	default:
		fmt.Println("age == ",age)
	}

9)switch 穿透-fallthrough ,如果在case语句块后增加fallthrough ,则会继续执行下一个case,也叫switch穿透

num := 10
	switch num {
	case 10:
		fmt.Println("ok1")
		fallthrough // 默认只能穿透一层
	case 20:
		fmt.Println("ok02")
	case 30:
		fmt.Println("ok03")
	default:
		fmt.Println("default")
	}

10)Type Switch: switch 语句还可以被用于type-switch来判断某个interface变量中实际指向的变量类型

var x interface{}
	var y = 10.0
	x = y
	switch i := x.(type) {
	case nil:
		fmt.Printf("x 的类型时是:%T",i)
	case int:
		fmt.Printf("x 是 int 型")
	case float64:
		fmt.Printf("x 是 float64 型")
	case func(int) float64:
		fmt.Printf("x 是 func(int) 型")
	case bool,string:
		fmt.Printf("x 是 bool 或 string 型")
	default:
		fmt.Printf("未知型")
	}

switch和if的比较

1)如果判断的具体数值不多,而且符合整数、浮点数、字符、字符串这几种类型。建议使用swtich语句,简洁高效。

2)其他情况:对区间判断和结果为bool类型的判断,使用if,if的使用范围更广

循环控制

for循环

语法格式

for 循环变量初始化;循环条件;循环变量迭代 {
    循环操作(语句)
}

 格式说明

  1. 循环变量初始化
  2. 循环条件
  3. 循环操作(语句) ,有人也叫循环体
  4. 循环变量迭代

执行顺序

  1. 执行循环变量初始化,比如i := 1
  2. 执行循环条件,比如i<=10
  3. 如果循环条件为真,就执行循环操作:比如 fmt.Println(“..."')
  4. 执行循环变量迭代﹐比如i++
  5. 反复执行2,3,4步骤,直到循环条件为False ,就退出for循环

流程图

使用细节

1)循环条件是返回一个布尔值的表达式

2)for 循环的第二种使用方式

for 循环判断条件 {
    循环执行语句
}

**  将变量初始化和变量迭代写到其它位置**

i := 10
for i<= 10{
    fmt.Println("hello world")
    i++
}

3)for循环的第三种使用方式

for {
    循环执行语句
}

上面的写法等价for ; ;是一个无限循环,通常需要配合break 语句使用

i := 10
for {
    if i <= 10{
        fmt.Println("hello world")
    }else {
        break
    }
    i++
}

4)Golang 提供for-range的方式,可以方便遍历字符串和数组,案例说明如何遍历字符串。

字符串遍历方式1-传统方式

var str string = "hello world"
for i := 0 ; i < len(str);i++{
    fmt.Printf("%c \n",str[i])
}

字符串遍历方式2-for - range

str := "hello world"
for index, val := range str {
   fmt.Printf("index = %d , val = %c \n", index, val)
}

** 如果我们的字符串含有中文,那么传统的遍历字符串方式,就是错误,会出现乱码。原因是传统的对字符串的遍历是按照字节来遍历,而一个汉字在utf8编码是对应3个字节。**

含汉字字符串的遍历

// 方法一  []rune切片
	str := "hello world ! 北京"
	str2 := []rune(str)
	for i := 0; i < len(str2); i++ {
		fmt.Printf("%c \n", str2[i])
	}

	// 方法二 for - range
	for index,val := range str {
		fmt.Printf("index = %d,val = %c \n",index,val)
	}

while和 do..while的实现

Go语言没有while和 do...while语法,这一点需要同学们注意一下,如果我们需要使用类似其它语言(比如 java / c 的 while和 do...while ),可以通过for循环来实现其使用效果

while循环的实现

循环变量初始化
for {
    if 循环条件表达式 {
        break
    }
    循环操作(语句)
    循环变量迭代
}

1)for循环是一个无限循环

2)break 语句就是跳出for循环

i := 1 // 初始化循环变量
	for {
		if i > 10 { // 循环条件
			break // 跳出for循环
		}
		fmt.Println("hell world!", i)
		i++ // 循环变量的迭代
	}

 do..while的实现

循环变量初始化
for {
    循环操作(语句)
    循环遍历迭代
    if 循环条件表达式 {
        break
}
}

1)上面的循环是先执行,在判断,因此至少执行一次。

2)当循环条件成立后,就会执行break, break就是跳出for循环,结束循环

i := 1 // 初始化循环变量
		fmt.Println("hell world!", i)
		i++ // 循环变量的迭代
	for {
		if i > 10 { // 循环条件
			break // 跳出for循环
		}
	}

多重循环控制

1)将一个循环放在另一个循环体内,就形成了嵌套循环。在外边的 for称为外层循环在里面的 for循环称为内层循环。【建议一般使用两层,最多不要超过3层】

2)实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环

3)外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次

跳转控制语句-break

break 语句用于终止某个语句块的执行,用于中断当前for循环或跳出 switch 语句。

{
    ......
    break
    ......
}

使用细节和注意事项

1)break 语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块

lable:
	for i := 0;i<10 ;i ++{
		for j := 0;j<10;j++{
			if j == 5{
				break lable
			}
			fmt.Println("j = ",j)
		}
	}

(1) break 默认会跳出最近的for 循环

(2) break后面可以指定标签,跳出标签对应的for循环

跳转控制语句-continue

continue语句用于结束本次循环,继续执行下一次循环。

continue语句出现在多层嵌套的循环语句体中时,和break使用方式一样 

{
    ......
    continue
    ......
}
lable:
	for i := 0;i<10 ;i ++{
		for j := 0;j<10;j++{
			if j == 5{
				continue lable
			}
			fmt.Println("j = ",j)
		}
	}

跳转控制语句-goto

1)Go 语言的 goto语句可以无条件地转移到程序中指定的行。

2)goto语句通常与条件语句配合使用。可用来实现条件转移,跳出循环体等功能。

3)在Go程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,使理解和调试程序都产生

goto label
......
label:statement


 

n := 30
	fmt.Println("1")
	if n > 20{
		goto label
	}
	fmt.Println(2)
	fmt.Println(3)
	label:
	fmt.Println(4)
	fmt.Println(5)

跳转控制语句-return

return使用在方法或者函数中,表示跳出所在的方法或函数

1)如果return是在普通的函数,则表示跳出该函数,即不再执行函数中 return后面代码,也可以理解成终止函数。

2)如果return是在main 函数,表示终止main函数,也就是说终止程序

defer - 延时机制

在函数中,程序员经常需要创建资源(比如:数据库连接、文件句柄、锁等),为了在函数执行完毕后,及时的释放资源,Go的设计者提供 defer (延时机制)

1)当go执行到一个defer时,不会立即执行defer后的语句,而是将defer后的语句压入到一个栈中,然后继续执行函数下一个语句。

2)当函数执行完毕后,在从defer 栈中,依次从栈顶取出语句执行(注:遵守栈先入后出的机制)

3)在defer将语句放入到栈时,也会将相关的值拷贝同时入栈。

func sum(n1 int, n2 int) int {
   //当执行到defer时,暂时不执行,会将defer后面的语句压入到独立的栈(defer栈)
   //当函数执行完毕后,再从defer栈,按照先入后出的方式出栈,执行
   defer fmt.Println("ok1 n1 = ", n1)
   defer fmt.Println("ok2 n2 = ", n2)

   n1++ // 11
   n2++ // 21
   res := n1 + n2
   fmt.Println("ok3 res = ", res)
   return res
}

func main() {
   res := sum(10, 20)
   fmt.Println("res = ", res)
}
// =======输出
ok3 res =  32
ok2 n2 =  20
ok1 n1 =  10
res =  32

defer的最佳实践

defer最主要的价值是在,当函数执行完毕后,可以及时的释放函数创建的资源

1)在golang编程中的通常做法是,创建资源后,比如(打开了文件,获取了数据库的链接,或者是锁资源),可以执行defer file.Close() defer connect.Close()

2)在defer后,可以继续使用创建资源.

3)当函数完毕后,系统会依次从 defer 栈中,取出语句,关闭资源.

4)这种机制,非常简洁,程序员不用再为在什么时机关闭资源而烦恼

相关文章