有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪" />

欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

理解Go流程控制與快樂路徑原則

 更新時間:2023年10月12日 08:40:04   作者:賈維斯Echo  
這篇文章主要為大家介紹了Go流程控制與快樂路徑原則的原理解析,
有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一、流程控制基本介紹

流程控制是每種編程語言控制邏輯走向和執(zhí)行次序的重要部分,流程控制可以說是一門語言的“經(jīng)脈”。

那么 Go 語言對分支與循環(huán)兩種控制結(jié)構(gòu)的支持是怎么樣的呢?針對程序的分支結(jié)構(gòu),Go 提供了 if 和 switch-case 兩種語句形式;我們就先從 Go 語言分支結(jié)構(gòu)之一的 if 語句開始講起。

二、if 語句

2.1 if 語句介紹

if 語句是 Go 語言中提供的一種分支控制結(jié)構(gòu),它也是 Go 中最常用、最簡單的分支控制結(jié)構(gòu)。它會根據(jù)布爾表達(dá)式的值,在兩個分支中選擇一個執(zhí)行。

2.2 單分支結(jié)構(gòu)的 if 語句形式

單分支結(jié)構(gòu)的if語句包含一個條件表達(dá)式和一個要執(zhí)行的代碼塊。如果條件表達(dá)式的值為true,則執(zhí)行代碼塊。如果條件表達(dá)式的值為false,則代碼塊將被跳過。以下是單分支結(jié)構(gòu)的if語句的一般形式:

if boolean_expression {
    // 新分支
}
// 原分支

這個 if 語句中的代碼執(zhí)行流程就等價于下面這幅流程圖:

  • boolean_expression是一個布爾表達(dá)式,通常返回truefalse
  • 如果boolean_expression的值為true,則執(zhí)行// 當(dāng)條件為真時執(zhí)行的代碼部分的代碼塊。
  • 如果boolean_expression的值為false,則代碼塊將被跳過,繼續(xù)執(zhí)行下一個語句。

2.3 Go 的 if 語句的特點(diǎn)

2.3.1 分支代碼塊左大括號與if同行

if 語句的分支代碼塊的左大括號與 if 關(guān)鍵字在同一行上,這是 Go 代碼風(fēng)格的統(tǒng)一要求,gofmt 工具會幫助我們實(shí)現(xiàn)這一點(diǎn);

2.3.2 條件表達(dá)式不需要括號

if 語句的布爾表達(dá)式整體不需要用括號包裹,這使得代碼更加簡潔。而且,if 關(guān)鍵字后面的條件判斷表達(dá)式的求值結(jié)果必須是布爾類型,即要么是 true,要么是 false

if runtime.GOOS == "darwin" {
    println("we are on MacOS")
}

如果判斷的條件比較多,我們可以用多個邏輯操作符連接起多個條件判斷表達(dá)式,比如這段代碼就是用了多個邏輯操作符 && 來連接多個布爾表達(dá)式:

if (runtime.GOOS == "darwin") && (runtime.GOARCH == "amd64") &&
        (runtime.Compiler != "gccgo") {
        println("we are using standard go compiler on Mac os for amd64")
    }

上面示例代碼中的每個布爾表達(dá)式都被小括號括上了,這是為了降低你在閱讀和理解這段代碼時,面對操作符優(yōu)先級的心智負(fù)擔(dān)。

三、操作符

3.1 邏輯操作符

邏輯操作符除了上面的 && 之外,Go 還提供了另外兩個邏輯操作符,如下表:

3.2 操作符的優(yōu)先級

一元操作符,比如上面的邏輯非操作符,具有最高優(yōu)先級,其他操作符的優(yōu)先級如下:

優(yōu)先級(從高到低)操作符列表
5*, /, %, <<, >>, &, &^
4+, -
3!=, ==, <, <=, >, >=
2&&
1\
  • 優(yōu)先級5的是乘、除、取模和位操作符
  • 優(yōu)先級4的是加法和減法運(yùn)算符
  • 優(yōu)先級3的是關(guān)系和相等運(yùn)算符
  • 優(yōu)先級2的是邏輯與
  • 優(yōu)先級最低的是邏輯或

操作符優(yōu)先級決定了操作數(shù)優(yōu)先參與哪個操作符的求值運(yùn)算,我們以下面代碼中 if 語句的布爾表達(dá)式為例:

func main() {
    a, b := false,true
    if a && b != true {
        println("(a && b) != true")
        return
    }
    println("a && (b != true) == false")
}

這段代碼會輸出得到的是 a && (b != true) == false。這是為什么呢?

這段代碼的關(guān)鍵就在于,if 后面的布爾表達(dá)式中的操作數(shù) b 是先參與 && 的求值運(yùn)算,還是先參與!= 的求值運(yùn)算。根據(jù)前面的操作符優(yōu)先級表,我們知道,!= 的優(yōu)先級要高于 &&,因此操作數(shù) b 先參與的是!= 的求值運(yùn)算,這樣 if 后的布爾表達(dá)式就等價于 a && (b != true) 。

針對以上問題,推薦在 if 布爾表達(dá)式中,使用帶有小括號的子布爾表達(dá)式來清晰地表達(dá)判斷條件。

這樣做不僅可以消除了自己記住操作符優(yōu)先級的學(xué)習(xí)負(fù)擔(dān),當(dāng)其他人閱讀你的代碼時,也可以很清晰地看出布爾表達(dá)式要表達(dá)的邏輯關(guān)系,這能讓我們代碼的可讀性更好,更易于理解,不會因記錯操作符優(yōu)先級順序而產(chǎn)生錯誤的理解。

三、if 多(N)分支結(jié)構(gòu)

3.1 if else(分支結(jié)構(gòu))

Go語言中if else(分支結(jié)構(gòu))條件判斷的格式如下:

if boolean_expression {
  // 分支1
} else {
  // 分支2
}

3.2 (N)分支結(jié)構(gòu)(if ... else if ... else)

if條件(N)分支結(jié)構(gòu)格式如下:

if boolean_expression1 {
  // 分支1
} else if boolean_expression2 {
  // 分支2

... ...

} else if boolean_expressionN {
  // 分支N
} else {
  // 分支N+1
}

我們以下面這個四分支的代碼為例,看看怎么拆解這個多分支結(jié)構(gòu):

if boolean_expression1 {
    // 分支1
} else if boolean_expression2 {
    // 分支2
} else if boolean_expression3 {
    // 分支3
} else {
    // 分支4
}

以下是一個示例,演示如何使用if-else結(jié)構(gòu)來判斷一個分?jǐn)?shù)的等級:

package main
import "fmt"
func main() {
    score := 85
    if score >= 90 {
        fmt.Println("A")
    } else if score >= 80 {
        fmt.Println("B")
    } else if score >= 70 {
        fmt.Println("C")
    } else {
        fmt.Println("D")
    }
}

四、if 語句的自用變量

無論是單分支、二分支還是多分支結(jié)構(gòu),我們都可以在 if 后的布爾表達(dá)式前,進(jìn)行一些變量的聲明,在 if 布爾表達(dá)式前聲明的變量,叫 if 語句的自用變量。顧名思義,這些變量只可以在 if 語句的代碼塊范圍內(nèi)使用,比如下面代碼中的變量 a、b 和 c:

func main() {
    if a, c := f(), h(); a > 0 {
        println(a)
    } else if b := f(); b > 0 {
        println(a, b)
    } else {
        println(a, b, c)
    }
}

我們可以看到自用變量聲明的位置是在每個 if 語句的后面,布爾表達(dá)式的前面,而且,由于聲明本身是一個語句,所以我們需要把它和后面的布爾表達(dá)式通過分號分隔開。

在 if 語句中聲明自用變量是 Go 語言的一個慣用法,這種使用方式直觀上可以讓開發(fā)者有一種代碼行數(shù)減少的感覺,提高可讀性。同時,由于這些變量是 if 語句自用變量,它的作用域僅限于 if 語句的各層隱式代碼塊中,if 語句外部無法訪問和更改這些變量,這就讓這些變量具有一定隔離性,這樣你在閱讀和理解 if 語句的代碼時也可以更聚焦。

五、if 語句的“快樂路徑”原則

上面我們已經(jīng)學(xué)了 if 分支控制結(jié)構(gòu)的三種形式了,從可讀性上來看,單分支結(jié)構(gòu)要優(yōu)于二分支結(jié)構(gòu),二分支結(jié)構(gòu)又優(yōu)于多分支結(jié)構(gòu)。那么顯然,我們在日常編碼中要減少多分支結(jié)構(gòu),甚至是二分支結(jié)構(gòu)的使用,這會有助于我們編寫出優(yōu)雅、簡潔、易讀易維護(hù)且不易錯的代碼。

首先,我們來看一段偽代碼段1:

//偽代碼段1:
func doSomething() error {
  if errorCondition1 {
    // some error logic
    ... ...
    return err1
  }
  // some success logic
  ... ...
  if errorCondition2 {
    // some error logic
    ... ...
    return err2
  }
  // some success logic
  ... ...
  return nil
}

我們看到單分支控制結(jié)構(gòu)的偽代碼段 1 有這幾個特點(diǎn):

  • 沒有使用 else 分支,失敗就立即返回;
  • “成功”邏輯始終“居左”并延續(xù)到函數(shù)結(jié)尾,沒有被嵌入到 if 的布爾表達(dá)式為 true 的代碼分支中;
  • 整個代碼段布局扁平,沒有深度的縮進(jìn);
  • 代碼的可讀性很高

我們來看一段偽代碼段2:

// 偽代碼段2:
func doSomething() error {
  if successCondition1 {
    // some success logic
    ... ...
    if successCondition2 {
      // some success logic
      ... ...
      return nil
    } else {
      // some error logic
      ... ...
      return err2
    }
  } else {
    // some error logic
    ... ...
    return err1
  }
}

偽代碼段 2 實(shí)現(xiàn)了同樣邏輯碼段 1,就使用了帶有嵌套的二分支結(jié)構(gòu),它的特點(diǎn)如下:

  • 整個代碼段呈現(xiàn)為“鋸齒狀”,有深度縮進(jìn);
  • “成功”邏輯被嵌入到 if 的布爾表達(dá)式為 true 的代碼分支中;

很明顯,偽代碼段 1 的邏輯更容易理解,也更簡潔。Go 社區(qū)把這種 if 語句的使用方式稱為 if 語句的“快樂路徑(Happy Path)”原則,所謂“快樂路徑”也就是成功邏輯的代碼執(zhí)行路徑,它的特點(diǎn)是這樣的:

  • 僅使用單分支控制結(jié)構(gòu);
  • 當(dāng)布爾表達(dá)式求值為 false 時,也就是出現(xiàn)錯誤時,在單分支中快速返回;
  • 正常邏輯在代碼布局上始終“靠左”,這樣讀者可以從上到下一眼看到該函數(shù)正常邏輯的全貌;
  • 函數(shù)執(zhí)行到最后一行代表一種成功狀態(tài)。

Go 社區(qū)推薦 Gopher 們在使用 if 語句時盡量符合這些原則,如果你的函數(shù)實(shí)現(xiàn)代碼不符合“快樂路徑”原則,你可以按下面步驟進(jìn)行重構(gòu):

  • 嘗試將“正常邏輯”提取出來,放到“快樂路徑”中;
  • 如果無法做到上一點(diǎn),很可能是函數(shù)內(nèi)的邏輯過

以上就是Go流程控制與快樂路徑原則的詳細(xì)內(nèi)容,更多關(guān)于Go流程控制路徑原則的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用golang實(shí)現(xiàn)在屏幕上打印進(jìn)度條的操作

    使用golang實(shí)現(xiàn)在屏幕上打印進(jìn)度條的操作

    這篇文章主要介紹了使用golang實(shí)現(xiàn)在屏幕上打印進(jìn)度條的操作,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Golang新提案:panic?能不能加個?PanicError?

    Golang新提案:panic?能不能加個?PanicError?

    這篇文章主要為大家介紹了Golang的新提案關(guān)于panic能不能加個PanicError的問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • go語言for循環(huán)中嵌套defer的執(zhí)行順序

    go語言for循環(huán)中嵌套defer的執(zhí)行順序

    在Go語言中,defer語句用于延遲函數(shù)調(diào)用的執(zhí)行,本文主要介紹了go語言for循環(huán)中嵌套defer的執(zhí)行順序,具有一定的參考價值,感興趣的可以了解一下
    2025-03-03
  • Golang 標(biāo)準(zhǔn)庫 tips之waitgroup詳解

    Golang 標(biāo)準(zhǔn)庫 tips之waitgroup詳解

    本篇文章給大家介紹Golang 標(biāo)準(zhǔn)庫 tips之waitgroup的相關(guān)知識,包括使用 channel 實(shí)現(xiàn) WaitGroup 的功能介紹,感興趣的朋友跟隨小編一起看看吧
    2021-07-07
  • 使用go語言實(shí)現(xiàn)Redis持久化的示例代碼

    使用go語言實(shí)現(xiàn)Redis持久化的示例代碼

    redis 是一個內(nèi)存數(shù)據(jù)庫,如果你把進(jìn)程殺掉,那么里面存儲的數(shù)據(jù)都會消失,那么這篇文章就是來解決 redis 持久化的問題,本文給大家介紹了使用go語言實(shí)現(xiàn)Redis持久化,需要的朋友可以參考下
    2024-07-07
  • Go語言實(shí)現(xiàn)RSA加解密算法詳解

    Go語言實(shí)現(xiàn)RSA加解密算法詳解

    隨著互聯(lián)網(wǎng)的高速發(fā)展,人們對安全的要求也越來越高,加解密也變得越來越重要,本文主要為大家介紹了Go語言中實(shí)現(xiàn)RSA加解密與簽名驗(yàn)證算法,希望對大家有所幫助
    2023-06-06
  • golang 連接mongoDB的方法示例

    golang 連接mongoDB的方法示例

    這篇文章主要介紹了golang 連接mongoDB的方法示例,詳細(xì)的介紹了golang的基礎(chǔ)知識和連接mongoDB的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • golang 獲取字符串長度的案例

    golang 獲取字符串長度的案例

    這篇文章主要介紹了golang 獲取字符串長度的案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 解決go mod私有倉庫拉取的問題

    解決go mod私有倉庫拉取的問題

    這篇文章主要介紹了解決go mod私有倉庫拉取的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • 基于go中fyne gui的通達(dá)信數(shù)據(jù)導(dǎo)出工具詳解

    基于go中fyne gui的通達(dá)信數(shù)據(jù)導(dǎo)出工具詳解

    這篇文章主要介紹了基于go中fyne gui的通達(dá)信數(shù)據(jù)導(dǎo)出工具,這是一個用 Go 語言開發(fā)的通達(dá)信數(shù)據(jù)導(dǎo)出工具,可以將通達(dá)信的本地數(shù)據(jù)導(dǎo)出為多種格式,方便用戶進(jìn)行數(shù)據(jù)分析和處理,需要的朋友可以參考下
    2024-12-12

最新評論