Golang通脈之流程控制詳情
前言:
流程控制是每種編程語(yǔ)言控制邏輯走向和執(zhí)行次序的重要部分,流程控制可以說(shuō)是一門語(yǔ)言的“經(jīng)脈”。
Go語(yǔ)言中最常用的流程控制有if和for,而switch和goto主要是為了簡(jiǎn)化代碼、降低重復(fù)代碼而生的結(jié)構(gòu),屬于擴(kuò)展類的流程控制。
1、if else(分支結(jié)構(gòu))
1.1 if條件判斷基本寫法
Go語(yǔ)言中if條件判斷的格式如下:
if 表達(dá)式1 {
分支1
} else if 表達(dá)式2 {
分支2
} else{
分支3
}
當(dāng)表達(dá)式1的結(jié)果為true時(shí),執(zhí)行分支1,否則判斷表達(dá)式2,如果滿足則執(zhí)行分支2,都不滿足時(shí),則執(zhí)行分支3。 if判斷中的else if和else都是可選的,可以根據(jù)實(shí)際需要進(jìn)行選擇。
關(guān)于 if 條件語(yǔ)句的使用有一些規(guī)則:
- if 后面的條件表達(dá)式不需要使用 (),這和有些編程語(yǔ)言不一樣,也更體現(xiàn) Go 語(yǔ)言的簡(jiǎn)潔;
- 每個(gè)條件分支(
if或者else)中的大括號(hào)是必須的,哪怕大括號(hào)里只有一行代碼(如示例); - if 緊跟的大括號(hào) { 不能獨(dú)占一行,
else前的大括號(hào) } 也不能獨(dú)占一行,否則會(huì)編譯不通過(guò); - 在
if……else條件語(yǔ)句中還可以增加多個(gè)else if,增加更多的條件分支。
1.2 if條件判斷特殊寫法
if條件判斷還有一種特殊的寫法,可以在 if 表達(dá)式之前添加一個(gè)執(zhí)行語(yǔ)句,再根據(jù)變量值進(jìn)行判斷:
func main() {
if i:=6; i >10 {
fmt.Println("i>10")
} else if i>5 && i<=10 {
fmt.Println("5<i<=10")
} else {
fmt.Println("i<=5")
}
}
2、for(循環(huán)結(jié)構(gòu))
Go 語(yǔ)言中的所有循環(huán)類型均可以使用for關(guān)鍵字來(lái)完成。
for循環(huán)的基本格式如下:
for 初始語(yǔ)句;條件表達(dá)式;更新語(yǔ)句{
循環(huán)體語(yǔ)句
}
條件表達(dá)式返回true時(shí)循環(huán)體不停地進(jìn)行循環(huán),直到條件表達(dá)式返回false時(shí)自動(dòng)退出循環(huán)。
func forDemo() {
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
for循環(huán)的初始語(yǔ)句可以被忽略,但是初始語(yǔ)句后的分號(hào)必須要寫,例如:
func forDemo2() {
i := 0
for ; i < 10; i++ {
fmt.Println(i)
}
}
for循環(huán)的初始語(yǔ)句和結(jié)束語(yǔ)句都可以省略,例如:
func forDemo3() {
i := 0
for i < 10 {
fmt.Println(i)
i++
}
}
這種寫法類似于其他編程語(yǔ)言中的while,在while后添加一個(gè)條件表達(dá)式,滿足條件表達(dá)式時(shí)持續(xù)循環(huán),否則結(jié)束循環(huán)。
2.1 無(wú)限循環(huán)
for {
循環(huán)體語(yǔ)句
}
for循環(huán)可以通過(guò)break、goto、return、panic語(yǔ)句強(qiáng)制退出循環(huán)。
在 Go 語(yǔ)言中,同樣支持使用 continue、break 控制 for 循環(huán):
continue 可以跳出本次循環(huán),繼續(xù)執(zhí)行下一個(gè)循環(huán)。
break 可以跳出整個(gè) for 循環(huán),哪怕 for 循環(huán)沒(méi)有執(zhí)行完,也會(huì)強(qiáng)制終止。
3、for range(鍵值循環(huán))
Go語(yǔ)言中可以使用for range遍歷數(shù)組、切片、字符串、map 及通道(channel)。
通過(guò)for range遍歷的返回值有以下規(guī)律:
- 數(shù)組、切片、字符串返回索引和值。
map返回鍵和值。- 通道(
channel)只返回通道內(nèi)的值。
注意:
與 for 不同的是,range 對(duì)每個(gè)迭代值都創(chuàng)建了一個(gè)拷貝。因此如果每次迭代的值內(nèi)存占用很小的情況下,for 和 range 的性能幾乎沒(méi)有差異,但是如果每個(gè)迭代值內(nèi)存占用很大,這種情況下差距就非常明顯了。
簡(jiǎn)單的例子證明 range 迭代時(shí),返回的是拷貝。
persons := []struct{ no int }{{no: 1}, {no: 2}, {no: 3}}
for _, s := range persons {
s.no += 10
}
for i := 0; i < len(persons); i++ {
persons[i].no += 100
}
fmt.Println(persons) // [{101} {102} {103}]
persons是一個(gè)長(zhǎng)度為 3 的切片,每個(gè)元素是一個(gè)結(jié)構(gòu)體。- 使用
range迭代時(shí),試圖將每個(gè)結(jié)構(gòu)體的 no 字段增加 10,但修改無(wú)效,因?yàn)?range返回的是拷貝。 - 使用 for 迭代時(shí),將每個(gè)結(jié)構(gòu)體的 no 字段增加 100,修改有效
range 在迭代過(guò)程中返回的是迭代值的拷貝,如果每次迭代的元素的內(nèi)存占用很低,那么 for 和 range 的性能幾乎是一樣,例如 []int。但是如果迭代的元素內(nèi)存占用較高,例如一個(gè)包含很多屬性的 struct 結(jié)構(gòu)體,那么 for 的性能將顯著地高于range,有時(shí)候甚至?xí)猩锨П兜男阅懿町?。?duì)于這種場(chǎng)景,建議使用 for,如果使用 range,建議只迭代下標(biāo),通過(guò)下標(biāo)訪問(wèn)迭代值,這種使用方式和 for 就沒(méi)有區(qū)別了。如果想使用 range 同時(shí)迭代下標(biāo)和值,則需要將切片/數(shù)組的元素改為指針,才能不影響性能。
4、switch case
使用switch語(yǔ)句可方便地對(duì)大量的值進(jìn)行條件判斷。
func switchDemo1() {
finger := 3
switch finger {
case 1:
fmt.Println("大拇指")
case 2:
fmt.Println("食指")
case 3:
fmt.Println("中指")
case 4:
fmt.Println("無(wú)名指")
case 5:
fmt.Println("小拇指")
default:
fmt.Println("無(wú)效的輸入!")
}
}
Go語(yǔ)言規(guī)定每個(gè)switch只能有一個(gè)default分支。
一個(gè)分支可以有多個(gè)值,多個(gè)case值中間使用英文逗號(hào)分隔。
func testSwitch3() {
switch n := 7; n {
case 1, 3, 5, 7, 9:
fmt.Println("奇數(shù)")
case 2, 4, 6, 8:
fmt.Println("偶數(shù)")
default:
fmt.Println(n)
}
}
分支還可以使用表達(dá)式,這時(shí)候switch語(yǔ)句后面不需要再跟判斷變量:
func switchDemo4() {
age := 30
switch {
case age < 25:
fmt.Println("好好學(xué)習(xí)吧")
case age > 25 && age < 35:
fmt.Println("好好工作吧")
case age > 60:
fmt.Println("好好享受吧")
default:
fmt.Println("活著真好")
}
}
在 Go 語(yǔ)言中,switch 的 case 從上到下逐一進(jìn)行判斷,一旦滿足條件,立即執(zhí)行對(duì)應(yīng)的分支并返回,其余分支不再做判斷。也就是說(shuō) Go 語(yǔ)言的 switch 在默認(rèn)情況下,case 最后自帶 break。這和其他編程語(yǔ)言不一樣,比如 C 語(yǔ)言在 case 分支里必須要有明確的 break 才能退出一個(gè) case。Go 語(yǔ)言的這種設(shè)計(jì)就是為了防止忘記寫 break 時(shí),下一個(gè) case 被執(zhí)行。
fallthrough語(yǔ)法可以執(zhí)行滿足條件的case的下一個(gè)case,是為了兼容C語(yǔ)言中的case設(shè)計(jì)的。
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
5、goto(跳轉(zhuǎn)到指定標(biāo)簽)
goto語(yǔ)句通過(guò)標(biāo)簽進(jìn)行代碼間的無(wú)條件跳轉(zhuǎn)。goto語(yǔ)句可以在快速跳出循環(huán)、避免重復(fù)退出上有一定的幫助。Go語(yǔ)言中使用goto語(yǔ)句能簡(jiǎn)化一些代碼的實(shí)現(xiàn)過(guò)程。
例如雙層嵌套的for循環(huán)要退出時(shí):
func gotoDemo1() {
var breakFlag bool
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
// 設(shè)置退出標(biāo)簽
breakFlag = true
break
}
fmt.Printf("%v-%v\n", i, j)
}
// 外層for循環(huán)判斷
if breakFlag {
break
}
}
}
使用goto語(yǔ)句能簡(jiǎn)化代碼:
func gotoDemo2() {
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if j == 2 {
// 設(shè)置退出標(biāo)簽
goto breakTag
}
fmt.Printf("%v-%v\n", i, j)
}
}
return
// 標(biāo)簽
breakTag:
fmt.Println("結(jié)束for循環(huán)")
}
6、break(跳出循環(huán))
break語(yǔ)句可以結(jié)束for、switch和select的代碼塊。
break語(yǔ)句還可以在語(yǔ)句后面添加標(biāo)簽,表示退出某個(gè)標(biāo)簽對(duì)應(yīng)的代碼塊,標(biāo)簽要求必須定義在對(duì)應(yīng)的for、switch和 select的代碼塊上。 舉個(gè)例子:
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("...")
}
7、continue(繼續(xù)下次循環(huán))
continue語(yǔ)句可以結(jié)束當(dāng)前循環(huán),開(kāi)始下一次的循環(huán)迭代過(guò)程,僅限在for循環(huán)內(nèi)使用。
在 continue語(yǔ)句后添加標(biāo)簽時(shí),表示開(kāi)始標(biāo)簽對(duì)應(yīng)的循環(huán)。例如:
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)
}
}
}
到此這篇關(guān)于Golang通脈之流程控制詳情的文章就介紹到這了,更多相關(guān)Golang通脈之流程控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go 語(yǔ)言中g(shù)in使用gzip壓縮遇到的問(wèn)題
這篇文章主要介紹了Go 語(yǔ)言中g(shù)in使用gzip壓縮遇到的問(wèn)題,需要的朋友可以參考下2017-09-09
Go調(diào)度器學(xué)習(xí)之協(xié)作與搶占詳解
如果某個(gè)G執(zhí)行時(shí)間過(guò)長(zhǎng),其他的G如何才能被正常調(diào)度,這就引出了接下來(lái)的話題:協(xié)作與搶占。本文將通過(guò)一些示例為大家詳細(xì)講講調(diào)度器中協(xié)作與搶占的相關(guān)知識(shí),需要的可以參考一下2023-04-04
go語(yǔ)言版的ip2long函數(shù)實(shí)例
這篇文章主要介紹了go語(yǔ)言版的ip2long函數(shù),實(shí)例分析了Go語(yǔ)言實(shí)現(xiàn)的ip2long函數(shù)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02
GoLang jwt無(wú)感刷新與SSO單點(diǎn)登錄限制解除方法詳解
這篇文章主要介紹了GoLang jwt無(wú)感刷新與SSO單點(diǎn)登錄限制解除方法,JWT是一個(gè)簽名的JSON對(duì)象,通常用作Oauth2的Bearer token,JWT包括三個(gè)用.分割的部分。本文將利用JWT進(jìn)行認(rèn)證和加密,感興趣的可以了解一下2023-03-03
Golang 統(tǒng)計(jì)字符串字?jǐn)?shù)的方法示例
本篇文章主要介紹了Golang 統(tǒng)計(jì)字符串字?jǐn)?shù)的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05
Go語(yǔ)言標(biāo)準(zhǔn)輸入輸出庫(kù)的基本使用教程
輸入輸出在任何一門語(yǔ)言中都必須提供的一個(gè)功能,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言標(biāo)準(zhǔn)輸入輸出庫(kù)的基本使用,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02
Go的固定時(shí)長(zhǎng)定時(shí)器和周期性時(shí)長(zhǎng)定時(shí)器
本文主要介紹了Go的固定時(shí)長(zhǎng)定時(shí)器和周期性時(shí)長(zhǎng)定時(shí)器,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08

