四、流程控制
在一个稍微复杂的程序中,会根据程序运行的一些条件进行相应的操作。比如,打开一个文件,如果失败,则退出程序,如果成功,则读取文件内容并打印。总的来说,Go 语言的流程控制主要有 if else、for、goto、switch case、defer、continue、break、return。不同于其他语言,Go 条件判断不需要用()括号包含。
-
if else
-
格式为 if exp {...} else {}。exp 为一个结果为bool类型的表达式,可以包含简短的变量申明赋值,函数求值操作。如果条件为真,则运行if{}后面的语句,否则,运行else 后面的语句。
if:
var x = 10
if x>5 {
fmt.Println("x > 5") // x > 5
}
if else:
var x = 2
if x>5 {
fmt.Println("x > 5")
} else {
fmt.Println("x <= 5") // x <= 5
}
exp表达式还可以包含一个简短的语句(赋值,函数求值等),如:
if x:=2; x>5{
fmt.Println("x > 5")
} else {
fmt.Println("x <= 5") // x <= 5
}
如果有多个条件:
下面是将百分制转化为评级的代码
var x = `成绩`
if x >= 90 {
fmt.Println("A")
} else if x >= 80 {
fmt.Println("B")
} else if x >= 70 {
fmt.Println("C")
} else if x >= 60 {
fmt.Println("D")
} else {
fmt.Println("不及格")
}
如果条件很多的话,太多的 if else 语句既影响美观,也影响代码的可读性。那有什么办法可以避免呢?那就是 switch case,接着往下看
-
switch case
-
格式如下:
switch sExp {
case exp1:
1....
case exp2:
2....
default:
3....
}
如果sExp 为exp1则执行1中的语句,如果为exp2则执行2中的语句,如果都不满足,则执行3中的语句。需要注意两点:
1、sExp 和exp1、exp2的类型必须一致,如果是bool类型的话,则sExp可以省略
2、一个case 分支的语句执行完成之后,不会再执行switch中其他分支的语句,对比其他语言,相当于Go后面自动追加了break语句,当然,你也可以在case中使用break来终止switch case。
给定一个数值,如果为1则输出1,如果为2则输出2,其他值输出/:
var x int = 3
switch x {
case 1:
fmt.Println("1")
case 2:
fmt.Println("2")
default:
fmt.Println("/")
}
上个百分制转换的例子,可以用switch来写,表达式结果为bool 则sExp可以省略:
var x = `成绩`
switch {
case x >= 90 :
fmt.Println("A")
case x >= 80 :
fmt.Println("B")
case x >= 70 :
fmt.Println("C")
case x >= 60 :
fmt.Println("D")
default:
fmt.Println("不及格")
}
如果在一个分支执行完成之后,还要继续执行其他分支呢?那就使用fallthrough
var x = `成绩`
switch {
case x >= 90 :
fmt.Println("x >= 90")
fallthrough
case x >= 80 :
fmt.Println("x >= 80")
fallthrough
case x >= 70 :
fmt.Println("x >= 70")
fallthrough
case x >= 60 :
fmt.Println("x >= 60")
default:
fmt.Println("不及格")
}
//x = 99 则输出
x >= 90
x >= 80
x >= 70
x >= 60
相同条件如果执行相同的语句,而且条件很多的话,使用 fallthrough可能会不太美观,毕竟编程是一种艺术,是吧?还有一种方式,相同条件可以用逗号(,)隔开,就像这样:
func shouldEscape(c byte) bool {
switch c {
case ' ', '?', '&', '=', '#', '+', '%':
return true
}
return false
}
-
for
-
Go中的循环只有一个,那就是for,那就意味着for是很强大的。for的格式:
for exp1; exp2; exp3 {
...
}
exp1为初始化语句,在for循环开始之前执行,而且只执行一次;
exp2为判断语句,结果为bool类型,为真则执行一次循环;
exp3为迭代语句,在每轮循环之后,下轮循环之前执行。
exp1、exp2、exp3都不是必须的。
100以内整数求和:
result := 0
for i:=1; i < 100; i++ {
result += i // result = result + i
}
fmt.Println(result)
省去初始化语句:
i, result := 1, 0
for ; i < 100; i++ {
result += i // result = result + i
}
fmt.Println(result)
省去初始化语句和迭代语句:
i, result := 0, 0
for i < 100 {
result += i // result = result + i
i++
}
fmt.Println(result)
省去所有语句,相当于其他语言的while循环:
i, result := 1, 0
for {
if i < 100 {
result += i // result = result + i
i++
} else {
break
}
}
fmt.Println(result)
怎么样?写法很多吧,而且上面几种写法的运行结果都一样。
有人会很奇怪,为什么最后一个程序没有一直运行下去?因为当i = 100时,流程break了,就是循环中断了。那就看下break
for循环可以嵌套,即在循环里面还有循环。比如,我们可以打印一个九九乘法表
for i:=1; i<10; i++ {
for j:=1; j<=i; j++ {
fmt.Fprintf(os.Stdout,"%2d\t",i*j)
}
fmt.Println()
}
fmt.Fprintf 是格式化输出的,也许你已经发现了os.Stdout其实就是屏幕。
-
break
-
break 就是用来中断 for 循环的
i := 1
for{
if i > 5{
break
}
fmt.Println(i)
i++
}
// 1 2 3 4 5
这样,就退出循环了。
break 还有一个作用,就是可以跳转到一个指定的lable。
for {
......
LABLE:
for ... {
.....
for {
if ... {
break LABLE
}
}
}
}
LABLE只是一个标签的名字而已,后面跟: 推荐名称为大写。这样当第三层for 满足某种情况的时候,就会跳转到lable 处,继续执行。当然,这个只是个例子,实际情况中应该尽量避免循环嵌套的情况。
如果只是想跳过某些情况,但是并不想中断整个循环,那怎么办?不用担心,你想到的Go已经帮你实现了,那就是continue,接着往下看
-
continue
-
接着上个例子,小于5的全部打印,,大于10则循环结束,其余的只打印偶数。
i := 1
for{
if i > 10 {
break
}
if i > 5 && i%2 != 0 {//当然可以判断为偶数就打印,这里只是为了举个例子
i++
continue
}
fmt.Println(i)
i++
}
-
return
-
return 语句用于退出当前方法。可以不带返回值,也可以带一个或者多个,这需要根据函数定义决定。
....
return
break + lable 的方式让程序跳转到指定地方,goto语句也可以实现跳转,但是,Go不推荐使用,所以在程序中应该极力避免使用。
defer 将会在下一篇讲到。