分类
顺序控制
图解
分支控制
单分支控制语句
语法结构
流程图解
双分支控制语句
基本语法
图解
多分支控制语句
基本语法
流程图
嵌套分支语句
switch分支控制
switch 的流程图
switch的使用的注意事项和细节
switch和if的比较
循环控制
for循环
语法格式
格式说明
执行顺序
流程图
使用细节
while和 do..while的实现
while循环的实现
do..while的实现
多重循环控制
跳转控制语句-break
使用细节和注意事项
跳转控制语句-continue
跳转控制语句-goto
跳转控制语句-return
defer - 延时机制
defer的最佳实践
1)顺序控制
2)分支控制
3)循环控制
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层内
2)匹配项后面也不需要再加 break
switch 表达式 {
case 表达式1,表达式2,...:
语句块
case 表达式3,表达式4,...:
语句块
.....
default:
语句块
}
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("周末")
}
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)
}
}
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("未知型")
}
1)如果判断的具体数值不多,而且符合整数、浮点数、字符、字符串这几种类型。建议使用swtich语句,简洁高效。
2)其他情况:对区间判断和结果为bool类型的判断,使用if,if的使用范围更广
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)
}
Go语言没有while和 do...while语法,这一点需要同学们注意一下,如果我们需要使用类似其它语言(比如 java / c 的 while和 do...while ),可以通过for循环来实现其使用效果
循环变量初始化
for {
if 循环条件表达式 {
break
}
循环操作(语句)
循环变量迭代
}
1)for循环是一个无限循环
2)break 语句就是跳出for循环
i := 1 // 初始化循环变量
for {
if i > 10 { // 循环条件
break // 跳出for循环
}
fmt.Println("hell world!", i)
i++ // 循环变量的迭代
}
循环变量初始化
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 语句用于终止某个语句块的执行,用于中断当前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语句出现在多层嵌套的循环语句体中时,和break使用方式一样
{
......
continue
......
}
lable:
for i := 0;i<10 ;i ++{
for j := 0;j<10;j++{
if j == 5{
continue lable
}
fmt.Println("j = ",j)
}
}
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使用在方法或者函数中,表示跳出所在的方法或函数
1)如果return是在普通的函数,则表示跳出该函数,即不再执行函数中 return后面代码,也可以理解成终止函数。
2)如果return是在main 函数,表示终止main函数,也就是说终止程序
在函数中,程序员经常需要创建资源(比如:数据库连接、文件句柄、锁等),为了在函数执行完毕后,及时的释放资源,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最主要的价值是在,当函数执行完毕后,可以及时的释放函数创建的资源
1)在golang编程中的通常做法是,创建资源后,比如(打开了文件,获取了数据库的链接,或者是锁资源),可以执行defer file.Close() defer connect.Close()
2)在defer后,可以继续使用创建资源.
3)当函数完毕后,系统会依次从 defer 栈中,取出语句,关闭资源.
4)这种机制,非常简洁,程序员不用再为在什么时机关闭资源而烦恼
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/zhjjly/article/details/126070054
内容来源于网络,如有侵权,请联系作者删除!