簡體   English   中英

golang的墮落似乎出人意料

[英]golang's fallthrough seems unexpected

我有以下代碼:

package main

import (
    "fmt"
)

func main() {
    switch {
    case 1 == 1:
        fmt.Println("1 == 1")
        fallthrough
    case 2 == 1:
        fmt.Println("2 == 1")
    }
}

在操場上打印兩條線 - 請參見此處的示例 我本來期望這個通過聲明包括評估下一個case陳述,但似乎並非如此。

當然,我總是可以使用一堆if語句,所以這不是一個真正的障礙,但我很好奇這里的意圖是什么,因為在我看來這是一個非顯而易見的結果。

有人在乎解釋嗎? 例如:在代碼中,如何執行第1和第3個案例?

語言規范

“fallthrough”語句將控制轉移到表達式“switch”語句中的下一個case子句的第一個語句。 它可能僅用作此類子句中的最終非空語句。

這似乎完美地描述了您觀察到的行為。

據推測,Go的墮落行為是以C為模型的,C總是像這樣工作。 在C, switch語句,如果它是這樣寫的Goto條件的,所以你的具體的例子會被編譯鏈只是速記:

    # Pseudocode
    if 1 == 1 goto alpha
    if 2 == 1 goto beta
alpha:
    fmt.Println("1 == 1")
beta:
    fmt.Println("2 == 1")

正如您所看到的,一旦執行進入alpha情況,它就會繼續向下流動,忽略beta標簽(因為標簽本身並沒有真正做任何事情)。 條件檢查已經發生,不會再發生。

因此,fallthrough switch語句的非直觀性質僅僅是因為switch語句是goto語句。

Switch不是一堆ifs。 它更類似於if {} else if {}構造,但有幾個曲折 - 即breakfallthrough 切換執行第一種和第三種情況是不可能的 - 交換機不會檢查每個條件,它會找到第一個匹配並執行它。 就這樣。

它的主要目的是遍歷可能值的列表並為每個值執行不同的代碼。 事實上,在C(其中switch語句來自)中,switch表達式只能是整數類型,case case值只能是switch表達式也將被比較的常量。 僅在最近,語言才開始在交換機案例中添加對字符串,布爾表達式等的支持。

至於通過邏輯,它也來自C.在C中沒有穿透運算符。在C執行進入下一種情況(不檢查大小寫值),除非遇到break操作符。 這種設計的原因是,有時您需要做一些特殊的事情,然后執行與其他情況相同的步驟。 所以,這種設計只允許這樣。 不幸的是,它很少有用,所以默認情況下,當程序員忘記放入一個break語句時會導致更多麻煩,然后實際上幫助真正省略了故意破壞。 因此,許多現代語言將此邏輯更改為默認情況下永遠不會失敗,並且如果實際需要掉線則需要明確的通過語句。

不幸的是,很難想出一個非常有用的實用例子,這個例子很短,足以適應答案。 正如我所說,這是相對罕見的。 但有時您需要編寫類似於此的代碼:

if x == a || x == b {
  if x == a {
    // do action a
  }
  // do action ab
} else if x == c {
   // do action c
} else if x == d {
  // do action d
}

事實上,我最近在一個項目中需要類似結構的代碼。 所以,我使用了switch語句。 它看起來像這樣:

switch x {
  case a: // do action a
          fallthrough
  case b: // do action ab
  case c: // do action c
  case d: // do action d
}

你從這個問題的轉換在功能上等同於:

if 1 == 1 || 2 == 1 {
    if 1 == 1 {
        fmt.Println("1 == 1")
    }
    fmt.Println("2 == 1")
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM