2011-01-30 30 views
14

我知道,關於在PHP 5.3中引入的goto聲明有otherquestionsPHP中goto的有效用例是什麼?

但我無法找到任何有體面答案,一切都是類型爲「不得已而爲之」,「XKCD」的「惡」,「壞」,「惡!」。但沒有有效的例子。只有沒有任何用途的陳述。或者說有一些罕見的用例(再次,沒有例子)。

因此,問題是:「PHP中goto的有效用例是什麼?」。答案是「是goto邪惡?」不受歡迎,並會得到降低。謝謝:)

還是有人有一個鏈接到RFC的決定解釋 - 我找不到一個。

+0

`goto`是方便,因爲紅鯡魚有關的語言結構的useful-或邪惡的討論,無論什麼實際用途。 – mario 2011-01-30 16:18:25

+1

@mario:我試圖讓我的問題清楚,我沒興趣知道它是否是邪惡的。這樣的問題是浪費時間。我對具體的例子感興趣。因此我認爲這不是一個「主觀的或議論性的」問題。 – NikiC 2011-01-30 16:29:58

+0

@NikiC,順便說一句,當你說你是一個[「PHP核心開發人員」(http://stackoverflow.com/users/385378/nikic),這是否意味着你懂C? – Pacerier 2015-07-12 16:55:02

回答

6

一種可能的使用(即然而,可以使用其它裝置來實現)是實施finite state machine的。

+1

有限狀態機就像解析器一樣嗎? – NikiC 2011-01-30 15:08:35

+1

http://en.wikipedia.org/wiki/Finite-state_machine – Mchl 2011-01-30 15:19:56

+0

嗯,這並不能幫助我很多。你能舉一個有限狀態機的例子或者它被使用的地方嗎?這篇Wiki文章相當理論化,我在那裏找不到應用程序。它 – NikiC 2011-01-30 15:24:45

2

goto運算符可用於打破多級循環。

這個特殊goto應用實例給出at goto manual page

你也不能跳進任何類型的循環或switch結構。你可能會跳出這些,常見的用法是使用goto代替多級別的休息。

2

轉到一直在大由專門的語句代替像continuebreaktry...catch。在與PHP合作的這些年中,我覺得它不會幫助我一次。在像C++這樣的沒有break x語句的語言中,它可以用來跳出嵌套循環,但是由於PHP有它,所以沒有理由。

Code Complete有關於gotos的非常好的和詳細的章節。引用最後兩段:

使用gotos是一個宗教問題。我的教條是,在現代語言中,你可以很容易地用等價的順序構造替換十個gotos中的九個。在這些簡單的情況下,你應該將習慣取而代之。在困難的情況下,您仍然可以在十種情況中的九種中解除goto:您可以將代碼分解爲更小的例程,使用try-finally,使用嵌套ifs,測試和重新測試狀態變量,或重構條件。在這些情況下消除goto比較困難,但這是很好的心理鍛鍊,本節討論的技巧爲您提供了實現這一目標的工具。

在goto是解決問題的合法解決方案的其餘100個案例中,清楚地記錄並使用它。如果你的雨靴已經開啓,那麼在街區四處走動以避免泥濘的水坑是不值得的。但請保持開放,以接受其他程序員建議的無風險方法。他們可能會看到你沒有的東西。

我覺得很難理解爲什麼PHP團隊不願意加入它(畢竟那些年我們沒有它而生活在和平中)。

5

PHP Architect - GOTO in PHP 5.3: is it Really That Evil?

本文給出了爲什麼GOTO可能是有用的一個簡短的概述,爲什麼我們在PHP有它(2004年起),爲什麼這是/是有爭議的。一般的答案似乎是:GOTO大多是無用的,應在非常狹窄的應用空間來避免,除非(如建立一個編譯器):

有一件事是肯定的:有一些應用,在其中一個優秀的開發人員可以把GOTO可以很好地用於生成更簡單,更高效的代碼,但它們可能不是您普通開發人員編寫的主流程序;因此,沒有經驗的程序員會使用GOTO來損害他們的代碼,這是一個合理的問題。

也看到一些文章中提到的原始新聞列表的討論/爭論:

也看到這個徹底的語言無關的討論有關GOTO considered harmful at C2 Wiki

3

我使用它的一種情況是當我進行多級檢查時,並且不想在檢查後跳到相關部分時添加額外的代碼。

例如,有一個系統檢查倉庫中各種機器的狀態,並使倉庫整體失效,並在任何一個系統的任何一個部分死亡時發出警報,使用僞代碼像這樣:

if(hsensor[status] != OK) { 
    alert = Humidity sensor hsensor[fail_id] failed with error hsensor[fail_error] 
    goto sendAlert; 
} 

if(cosensor[status] != OK) { 
    alert = Co2 sensor cosensor[fail_id] failed with error cosensor[fail_error] 
    goto sendAlert; 
} 

這樣,如果什麼失敗,我可以跳過所有其他檢查,並通過與警報直行。無論誰在打電話都會收到警報,並提取所有稱爲警報的功能的完整結果,以便他們能夠修復警報。