流程控制
Go语言基本上继承了C/C++语言所有流程控制语句
流程控制语句主要包括:条件判断语句(if和switch)、循环控制语句(for、break和continue)和跳转语句(goto)。
Go语言中,通过if关键字构成的条件判断语句进行条件判断,格式如下:
1 2 3 4 5 6 7
| if 表达式1 { 分支1 } else if 表达式2 { 分支2 } else { 分支3 }
|
注意⚠:表达式后跟的左括号必须与表达式放在同一行中,否则程序在编译时将会触发错误,导致程序编译无法通过。另外,if、else if和else分支中对应的右括号可以另外换行,也可以与对应的左括号处在同一行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package main
import "fmt"
func main() { a := 101 if a > 100 { fmt.Println(a,"> 100") } else if a == 100 { fmt.Println(a,"= 100") } else { fmt.Println(a,"< 100") } }
|
if还有一种较为常见的写法,就是在if的表达式前添加一个语句,使用变量接收语句返回的值,通过对该变量的判断再选择执行的分支。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package main
import ( "fmt" "runtime" )
func main() { if num := runtime.NumCPU();num >=1 { fmt.Println("程序使用的CPU核心数为:",num) } }
|
注意⚠: 是在if表达式前定义num变量,num变量的作用域仅限于该分支中,程序的执行结果与宿主机的配置有关。
Go语言中的循环逻辑通过for关键字实现。不同于其他编程语言,Go语言没有while关键字,不存在while循环。
for循环格式如下:
1 2 3
| for 初始语句;条件表达式;赋值表达式 { 循环体 }
|
循环体中代码会不断地被执行,直到条件表达式的结果为false,程序才会继续执行for循环之后的程序代码。其中,初始语句、条件表达式和赋值表达式都是可选的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package main
import "fmt"
func main() { for i:=1;i<=5;i++{ fmt.Println(i) } } package main
import "fmt"
func main() { for i:=1;i<=5;i++{ fmt.Println(i) } }
|
break语句可以用来结束for循环,而且可以在语句后面添加标签,表示退出标签对应的代码块逻辑。
注意⚠: break语句如果不带标签,则默认跳出最内层的for循环。
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
| package main
import "fmt"
func main() { i := 1 for { for { if i > 5 { fmt.Println("跳出内层for循环") break } fmt.Println(i) i ++ } fmt.Println("跳出外层for循环") break } }
|
也可以使用带标签的break语句,直接跳出最外层的for循环:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package main
import "fmt"
func main() { i := 1 OuterLoop: for { for { if i > 5 { break OuterLoop } fmt.Println(i) i++ } } }
|
continue语句可以立即结束当前循环体中的逻辑,开始下一次循环。和break语句类似,continue语句后也可跟标签,表示开始标签所对应的循环。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package main
import "fmt"
func main(){ OuterLoop: for i := 0;i < 2;i++{ for j := 0;j < 3;j++ { if j == 1 { fmt.Println(i,j) continue OuterLoop } } } }
|
switch语句常用于基于大量不同条件来执行不同动作,每一个条件对应一个case分支。语句的执行过程从上至下,直到找到匹配项,匹配项后面也不需要再加break。
每一个switch语句只能包含一个可选的default分支,若没有找到匹配项,会默认执行default分支中的代码块。
Go语言中的switch语法如下:
1 2 3 4 5 6 7 8
| switch var1 { case value1: 代码块1 case value2: 代码块2 default: 代码块3 }
|
变量var1可以是任何类型,但value1和value2必须是相同的类型或最终结果为相同类型的表达式。每个case分支后可跟多个可能符合条件的值,使用逗号分隔它们,例如:case value1,value2,value3。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package main
import "fmt"
func main() { switch 1+1 { case 1: fmt.Println("1+1=1") case 2: fmt.Println("1+1=2") case 3: fmt.Println("1+1=3") default: fmt.Println("1+1不等于1或2或3") } }
|
默认情况下,switch匹配成功后就不会执行后续其他case,如果我们需要无条件强制执行后面的 case,可以使用fallthrough关键字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package main
import "fmt"
func main() { switch { case false: fmt.Println("我是第一个分支 条件为false") fallthrough case true: fmt.Println("我是第二个分支 条件为true") fallthrough case false: fmt.Println("我是第三个分支 条件为false") fallthrough default: fmt.Println("我是默认case")
} }
|
上述示例中,switch语句省略了条件表达式,表达式由下面的case给出。
goto语句用于代码间的无条件跳转,格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package main
import "fmt"
func main() { fmt.Println("Hello") goto sign fmt.Println("别执行") sign: fmt.Println("world") }
|
一般情况下,在程序中不建议使用goto语句,过多的goto语句会破坏程序结构,使程序的可读性变差。
小结
Go语言的流程控制语句主要包括:条件判断语句(if和switch)、循环控制语句(for、break和continue)和跳转语句(goto)。
- Go语言中的循环逻辑通过for关键字实现,不存在while循环。
- switch语句常用于基于大量不同条件来执行不同动作,每一个条件对应一个case分支。
- 一般情况下,在程序中不建议使用goto语句,过多的goto语句会破坏程序结构,使程序的可读性变差。
循环嵌套
一个循环结构内可以含有另一个循环,这被称为循环嵌套,又称多重循环。常用的循环嵌套是二重循环,外层循环称为外循环,内层循环称为内循环。
双重循环的结构:
1 2 3 4 5 6 7 8
| for (初始语句;条件表达式;赋值表达式) { 循环体 for(初始语句;条件表达式;赋值表达式) { 循环体 } }
|
上面的结构共由两个for循环组成,它们之间的层次关系是一个嵌套住另一个,我们把这种关系叫作嵌套关系。这种层次关系是唯一且不可改变的。
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
| package main
import "fmt"
func pyramid(n int) { for i:=1;i<=n;i++ { for j:=1;j<=n-i;j++{ fmt.Print(" ") } for k:=1;k<=2 * i-1;k++{ fmt.Print("*") } fmt.Println() } }
func main() { x := 9 pyramid(x) }
* *** ***** ******* ********* *********** ************* *************** *****************
|
斐波那契数列
斐波那契数列,又称黄金分割数列,因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为兔子数列,指的是这样一个数列:1、1、2、3、5、8、13、21、34……这个数列从第三项开始,每一项都等于前两项之和。斐波那契数列在现代物理、准晶体结构、化学等领域都有直接的应用。
那么,我们是否可以编写一个斐波那契数列的程序,输入第n项,程序输出对应第n项的值?答案是肯定的,最常见的实现方式就是循环和递归。
在Go语言中,实现斐波那契数列的程序如下:
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
| package main
import "fmt"
func fibonacci(n int) (res int) { a:=1 b:=1 for i:=2;i<n;i++{ c:=b b = a+b a=c } return b }
func main() { n:=9 fmt.Printf("斐波那契数列第%d项值为%d",n,fibonacci(n)) }
|
对于斐波那契数列,我们也可以使用递归来实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package main
import "fmt"
func fibonacci(n int) (res int) { if n==1 || n==2{ return 1 }else{ return fibonacci(n-2)+fibonacci(n-1) } }
func main(){ n:=6 fmt.Printf("斐波那契数列第%d项值为%d",n,fibonacci(n)) }
|
运算过程:
在使用递归方法来实现斐波那契数列时,我们也可以用switch分支来进行代替:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package main
import "fmt"
func f(n int) (rec int) { switch n { case 1: return 1 case 2: return 1 default: return f(n-2) + f(n-1) }
}
func main() { n := 6 fmt.Println(f(n)) }
|