[TOC]
# 流程控制
Go語言中最常用的流程控制有`if`和`for`,而`switch`和`goto`主要是為了簡化代碼、降低重復代碼而生的結構,屬于擴展類的流程控制。
## if else(分支結構)
`if`條件判斷的格式如下:
~~~
if 表達式1 {
分支1
} else if 表達式2 {
分支2
} else{
分支3
}
~~~
eg1:
~~~
func ifDemo1() {
score := 65
if score >= 90 {
fmt.Println("A")
} else if score > 75 {
fmt.Println("B")
} else {
fmt.Println("C")
}
}
~~~
### if條件判斷特殊寫法
if條件判斷還有一種特殊的寫法,可以在 if 表達式之前添加一個執行語句,再根據變量值進行判斷
eg2:
~~~
func ifDemo2() {
if score := 65; score >= 90 {
fmt.Println("A")
} else if score > 75 {
fmt.Println("B")
} else {
fmt.Println("C")
}
}
~~~
還可以進行`if ... else` 的嵌套
## for(循環結構)
所有循環類型均可以使用`for`關鍵字來完成。
for循環的基本格式如下:
~~~
for 初始語句;條件表達式;結束語句{
循環體語句
}
~~~
條件表達式返回`true`時循環體不停地進行循環,直到條件表達式返回`false`時自動退出循環。
~~~
func Demo() {
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
~~~
for循環的初始語句可以被忽略,但是初始語句后的分號必須要寫,例如:
~~~go
func Demo2() {
i := 0
for ; i < 10; i++ {
fmt.Println(i)
}
}
~~~
for循環的初始語句和結束語句都可以省略,例如:
~~~
func Demo3() {
i := 0
for i < 10 {
fmt.Println(i)
i++
}
}
~~~
這種寫法類似于其他編程語言中的`while`,在`while`后添加一個條件表達式,滿足條件表達式時持續循環,否則結束循環。
### 無限循環
~~~
for {
循環體語句
}
~~~
for循環可以通過`break`、`goto`、`return`、`panic`語句強制退出循環。
## for range(鍵值循環)
Go語言中可以使用`for range`遍歷數組、切片、字符串、map 及通道(channel)。 通過`for range`遍歷的返回值有以下規律:
1. 數組、切片、字符串返回索引和值。
2. map返回鍵和值。
3. 通道(channel)只返回通道內的值。
## switch case
使用`switch`語句可方便地對大量的值進行條件判斷。
~~~
func switchDemo() {
finger := 3
switch finger {
case 1:
fmt.Println("大拇指")
case 2:
fmt.Println("食指")
case 3:
fmt.Println("中指")
case 4:
fmt.Println("無名指")
case 5:
fmt.Println("小拇指")
default:
fmt.Println("無效的輸入!")
}
}
~~~
Go語言規定每個`switch`只能有一個`default`分支。
一個分支可以有多個值,多個case值中間使用英文逗號分隔。
~~~
func testSwitch3() {
switch n := 7; n {
case 1, 3, 5, 7, 9:
fmt.Println("奇數")
case 2, 4, 6, 8:
fmt.Println("偶數")
default:
fmt.Println(n)
}
}
~~~
分支還可以使用表達式,這時候switch語句后面不需要再跟判斷變量。例如:
~~~
func switchDemo4() {
age := 30
switch {
case age < 25:
fmt.Println("好好學習吧")
case age > 25 && age < 35:
fmt.Println("好好工作吧")
case age > 60:
fmt.Println("好好享受吧")
default:
fmt.Println("活著真好")
}
}
~~~
`fallthrough`語法可以執行滿足條件的case的下一個case,是為了兼容C語言中的case設計的。
~~~go
func switchDemo5() {
s := "a"
switch {
case s == "a":
fmt.Println("a")
fallthrough
case s == "b":
fmt.Println("b")
case s == "c":
fmt.Println("c")
default:
fmt.Println("...")
}
}
輸出:a
b
~~~
## goto(跳轉到指定標簽)
`goto`語句通過標簽進行代碼間的無條件跳轉。`goto`語句可以在快速跳出循環、避免重復退出上有一定的幫助。Go語言中使用`goto`語句能簡化一些代碼的實現過程
~~~
func gotoDemo2() {
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
// 設置退出標簽
goto breakTag
}
fmt.Printf("%v-%v\n", i, j)
}
}
return
// 標簽
breakTag:
fmt.Println("結束for循環")
}
~~~
## break(跳出循環)
`break`語句可以結束`for`、`switch`和`select`的代碼塊。
`break`語句還可以在語句后面添加標簽,表示退出某個標簽對應的代碼塊,標簽要求必須定義在對應的`for`、`switch`和`select`的代碼塊上。 eg:
~~~
func breakDemo1() {
BREAKDEMO1:
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
break BREAKDEMO1
}
fmt.Printf("%v-%v\n", i, j)
}
}
fmt.Println("...")
}
~~~
`注:break + 代碼塊名稱 ` 是一個退出循環的小技巧
## continue(繼續下次循環)
`continue`語句可以結束當前循環,開始下一次的循環迭代過程,僅限在`for`循環內使用。
在`continue`語句后添加標簽時,表示開始標簽對應的循環。
eg:
~~~
func continueDemo() {
forloop1:
for i := 0; i < 5; i++ {
// forloop2:
for j := 0; j < 5; j++ {
if i == 2 && j == 2 {
continue forloop1
}
fmt.Printf("%v-%v\n", i, j)
}
}
}
~~~
`continue + 代碼塊標簽 `和 `break + 代碼塊名稱` 有異曲之處
##select
select 隨機執行一個可運行的 case。如果沒有 case 可運行,它將阻塞,直到有 case 可運行。一個默認的子句應該總是可運行的。
~~~
select{
case 條件 ?:
? ? ? TODO you want
case 條件 ?:
? ? ? ?TODO you want
/* 你可以定義任意數量的 case */
default:/* 可選 */
? ? ? ??TODO you want
}
~~~
select 語句的語法:
* 每個 case 都必須是一個通信
* 所有 channel 表達式都會被求值
* 所有被發送的表達式都會被求值
* 如果任意某個通信可以進行,它就執行,其他被忽略。
* 如果有多個 case 都可以運行,Select 會隨機公平地選出一個執行。其他不會執行。
否則:
1. 如果有 default 子句,則執行該語句。
2. 如果沒有 default 子句,select 將阻塞,直到某個通信可以運行;Go 不會重新對 channel 或值進行求值。
~~~
packagemain
import"fmt"
func main(){
var c1, c2, c3 chan int
var i1, i2 int
select{
case i1=<-c1:
? ? ? ? ?fmt.Printf("received ",i1," from c1 \n")
case c2 <-i2:
? ? ? ? ?fmt.Printf("sent ",i2," to c2 \n")
case i3,ok:=(<-c3):// same as: i3, ok := <-c3
if ok{
? ? ? ? fmt.Printf("received ",i3," from c3 \n")
} else {
? ? ? ? ?fmt.Printf("c3 is closed \n")
}
default:
? ? ? ? ?fmt.Printf("no communication \n")
}
}
~~~
- Go準備工作
- 依賴管理
- Go基礎
- 1、變量和常量
- 2、基本數據類型
- 3、運算符
- 4、流程控制
- 5、數組
- 數組聲明和初始化
- 遍歷
- 數組是值類型
- 6、切片
- 定義
- slice其他內容
- 7、map
- 8、函數
- 函數基礎
- 函數進階
- 9、指針
- 10、結構體
- 類型別名和自定義類型
- 結構體
- 11、接口
- 12、反射
- 13、并發
- 14、網絡編程
- 15、單元測試
- Go常用庫/包
- Context
- time
- strings/strconv
- file
- http
- Go常用第三方包
- Go優化
- Go問題排查
- Go框架
- 基礎知識點的思考
- 面試題
- 八股文
- 操作系統
- 整理一份資料
- interface
- array
- slice
- map
- MUTEX
- RWMUTEX
- Channel
- waitGroup
- context
- reflect
- gc
- GMP和CSP
- Select
- Docker
- 基本命令
- dockerfile
- docker-compose
- rpc和grpc
- consul和etcd
- ETCD
- consul
- gin
- 一些小點
- 樹
- K8s
- ES
- pprof
- mycat
- nginx
- 整理后的面試題
- 基礎
- Map
- Chan
- GC
- GMP
- 并發
- 內存
- 算法
- docker