क्या लूप और फ़ंक्शंस का समर्थन करने वाली भाषा में 'गोटो' का उपयोग करना कभी फायदेमंद है? यदि हां, तो क्यों?


201

मैं लंबे समय से इस धारणा के अधीन हूं कि gotoयदि संभव हो तो इसका उपयोग कभी नहीं किया जाना चाहिए। दूसरे दिन libavcodec (जो C में लिखा गया है) का उपयोग करते हुए, मैंने इसके कई उपयोगों पर ध्यान दिया। क्या कभी gotoऐसी भाषा में उपयोग करना फायदेमंद है जो छोरों और कार्यों का समर्थन करती है? यदि हां, तो क्यों?

जवाबों:


242

"गोटो" कथन का उपयोग करने के कुछ कारण हैं जिनके बारे में मुझे पता है (कुछ ने पहले ही इस पर बात की है):

सफाई से एक समारोह से बाहर निकलना

अक्सर एक फ़ंक्शन में, आप संसाधनों को आवंटित कर सकते हैं और कई स्थानों पर बाहर निकलने की आवश्यकता हो सकती है। प्रोग्रामर अपने कोड को फंक्शन के अंत में रिसोर्स क्लीनअप कोड लगाकर सरल बना सकते हैं, और फंक्शन के सभी "एक्जिट पॉइंट्स" को क्लीनअप लेबल मिल जाएगा। इस तरह, आपको फ़ंक्शन के प्रत्येक "निकास बिंदु" पर सफाई कोड लिखना नहीं है।

नेस्टेड छोरों से बाहर निकलना

यदि आप एक नेस्टेड लूप में हैं और सभी छोरों को तोड़ने की जरूरत है , तो एक गोटो ब्रेक स्टेटमेंट्स और इफ-चेक की तुलना में इसे बहुत साफ और सरल बना सकता है।

निम्न स्तर के प्रदर्शन में सुधार

यह केवल परफेक्ट-क्रिटिकल कोड में मान्य है, लेकिन गोटो स्टेटमेंट बहुत तेज़ी से निष्पादित होते हैं और किसी फ़ंक्शन के माध्यम से आगे बढ़ने पर आपको बढ़ावा दे सकते हैं। हालांकि, यह एक दोधारी तलवार है, क्योंकि एक संकलक आमतौर पर कोड को अनुकूलित नहीं कर सकता है जिसमें गोटो शामिल हैं।

ध्यान दें कि इन सभी उदाहरणों में, गोटो एकल फ़ंक्शन के दायरे तक ही सीमित हैं।


15
नेस्टेड लूप से बाहर निकलने का सही तरीका आंतरिक लूप को एक अलग विधि में रिफ्लेक्टर करना है।
जसन

129
@ जेसन - बाह। वह बैल का भार है। के gotoसाथ प्रतिस्थापित returnकेवल मूर्खतापूर्ण है। यह किसी भी चीज़ को "रिफैक्टिंग" नहीं कर रहा है, यह सिर्फ "नामकरण" है ताकि उन लोगों को जो कि एक gotoतंग वातावरण में पले-बढ़े (यानी हम सभी) एक नैतिक रूप से किस राशि का उपयोग करने के बारे में बेहतर महसूस करते हैं goto। मैं बहुत से लूप को देखना पसंद करता हूं जहां मैं इसका उपयोग करता हूं और थोड़ा देखता हूंgoto , जो अपने आप में सिर्फ एक उपकरण है , यह देखने के लिए कि किसी ने लूप को कहीं से स्थानांतरित कर दिया है सिर्फ एक से बचने के लिए goto
क्रिस लुत्ज़

18
ऐसे स्थान हैं जहां गोट्स महत्वपूर्ण हैं: उदाहरण के लिए, एक अपवाद-कम C ++ वातावरण। सिल्वरलाइट स्रोत में हमारे पास सुरक्षित फ़ंक्शन के लिए हजारों (या अधिक) गोटो स्टेटमेंट हैं जो मैक्रोज़ के उपयोग के माध्यम से मौजूद हैं - प्रमुख मीडिया कोडेक्स और लाइब्रेरी अक्सर रिटर्न मान और कभी अपवाद के माध्यम से काम करते हैं, और इन त्रुटि हैंडलिंग तंत्र को संयोजित करना मुश्किल है एक एकल प्रदर्शन तरीका है।
जेफ विलकॉक्स

79
यह ध्यान देने योग्य है कि break, continue, returnमूल रूप से कर रहे हैं goto, बस अच्छा पैकेजिंग में।
el.pescado

16
मैं यह नहीं देखता कि do{....}while(0)गोटो से बेहतर विचार कैसे माना जाता है, इस तथ्य के अलावा कि यह जावा में काम करता है।
जेरेमी सूची

906

प्रत्येक व्यक्ति जो gotoप्रत्यक्ष या अप्रत्यक्ष रूप से उद्धृत करता है, अपनी स्थिति को पुष्ट करने के लिए एद्गर दिज्क्स्ट्रा के गोटो ने हानिकारक लेख पर विचार किया । बहुत खराब दिज्क्स्ट्रा के लेख का वस्तुतः कुछ भी नहीं है जिस तरह से gotoइन दिनों बयानों का उपयोग किया जाता है और इस प्रकार जो लेख कहता है वह आधुनिक प्रोग्रामिंग दृश्य के लिए कोई उपयुक्तता नहीं है। gotoअब एक धर्म पर -less मेम verges, अपने शास्त्रों के सही नीचे उच्च, इसकी उच्च पुजारियों और कथित विधर्मियों की shunning (या बुरा) पर से तय करती।

आइए, विषय पर थोड़ा प्रकाश डालने के लिए दीजकस्ट्रा के पेपर को संदर्भ में रखें।

जब दिक्जस्त्र ने अपने पत्र को लिखा, उस समय की लोकप्रिय भाषाएं बेसिक, फोरट्रान (पहले की बोलियाँ) और विभिन्न विधानसभा भाषाओं की तरह असंरचित प्रक्रियात्मक थीं। यह उच्च स्तर की भाषाओं का उपयोग करने वाले लोगों के लिए उनके कोड बेस के सभी मोड़ पर कूदने के लिए किया गया था , निष्पादन के विपरीत धागे जिसने "स्पेगेटी कोड" शब्द को जन्म दिया। आप इसे माइक मेफील्ड द्वारा लिखे गए क्लासिक ट्रेक गेम पर रोककर देख सकते हैं और यह पता लगाने की कोशिश कर रहे हैं कि चीजें कैसे काम करती हैं। उस पल को देखने के लिए कुछ पल निकालें।

टीएचआईएस "स्टेटमेंट टू गो का बेलगाम उपयोग" है कि 1968 में दिक्जस्ट्रा अपने पेपर के खिलाफ रेलिंग कर रहा था। यह वह माहौल है जिसमें वह रहता था, जिससे वह उस पेपर को लिखता था। किसी भी बिंदु पर आपको अपने कोड में कहीं भी कूदने की क्षमता जो आपको पसंद है वह वही था जो वह आलोचना कर रहा था और मांग को रोक दिया गया था। तुलना करने के लिए कि gotoसी या अन्य ऐसी आधुनिक भाषाओं में एनीमिक शक्तियां बस अदृश्य हैं।

मैं पहले से ही कृषकों के उठे हुए मंत्रों को सुन सकता हूं क्योंकि वे विधर्मी का सामना करते हैं। "लेकिन," वे जाप करेंगे, "आप gotoसी में पढ़ने के लिए कोड को बहुत मुश्किल बना सकते हैं ।" अरे हां? आप बिना कोड के भी पढ़ना मुश्किल बना सकते हैं goto। इस तरह:

#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}

gotoदृष्टि में नहीं है , इसलिए इसे पढ़ना आसान होना चाहिए, है ना? या इस बारे में कैसे:

a[900];     b;c;d=1     ;e=1;f;     g;h;O;      main(k,
l)char*     *l;{g=      atoi(*      ++l);       for(k=
0;k*k<      g;b=k       ++>>1)      ;for(h=     0;h*h<=
g;++h);     --h;c=(     (h+=g>h     *(h+1))     -1)>>1;
while(d     <=g){       ++O;for     (f=0;f<     O&&d<=g
;++f)a[     b<<5|c]     =d++,b+=    e;for(      f=0;f<O
&&d<=g;     ++f)a[b     <<5|c]=     d++,c+=     e;e= -e
;}for(c     =0;c<h;     ++c){       for(b=0     ;b<k;++
b){if(b     <k/2)a[     b<<5|c]     ^=a[(k      -(b+1))
<<5|c]^=    a[b<<5      |c]^=a[     (k-(b+1     ))<<5|c]
;printf(    a[b<<5|c    ]?"%-4d"    :"    "     ,a[b<<5
|c]);}      putchar(    '\n');}}    /*Mike      Laman*/

gotoवहां भी नहीं । इसलिए इसे पठनीय होना चाहिए।

इन उदाहरणों से मेरा क्या कहना है? यह ऐसी भाषा सुविधाएँ नहीं हैं जो अपठनीय, अचूक कोड बनाती हैं। यह वाक्य रचना नहीं है जो इसे करता है। यह बुरा प्रोग्रामर है जो इसका कारण बनता है। और खराब प्रोग्रामर, जैसा कि आप उस उपरोक्त आइटम में देख सकते हैं, किसी भी भाषा की सुविधा को अपठनीय और अनुपयोगी बना सकते हैं। forलूप की तरह वहाँ। (आप उन्हें देख सकते हैं, है ना?)

अब निष्पक्ष होने के लिए, कुछ भाषा निर्माण दूसरों की तुलना में दुरुपयोग करना आसान है। यदि आप एक सी प्रोग्रामर हैं, तो, मैं #defineलंबे समय तक उपयोग के बारे में 50% से अधिक निकटता से पहले सहकर्मी हूँ, जिसके खिलाफ मैं एक बड़े पैमाने पर जाऊंगा goto!

इसलिए, जिन लोगों ने इसे पढ़ने के लिए परेशान किया है, उनके लिए ध्यान देने योग्य कई महत्वपूर्ण बिंदु हैं।

  1. gotoबयानों पर डीजकस्ट्रा के कागज को एक प्रोग्रामिंग वातावरण के लिए लिखा गया था, जहां सबसे आधुनिक भाषाओं में एक कोडांतरक की तुलना में बहुत अधिक संभावित रूप से हानिकारक gotoथा ।
  2. स्वचालित gotoरूप से इस वजह से सभी उपयोगों को फेंकना तर्कसंगत होने के बारे में है जैसा कि "मैंने एक बार मज़े करने की कोशिश की, लेकिन यह पसंद नहीं आया इसलिए अब मैं इसके खिलाफ हूं"।
  3. gotoकोड में आधुनिक (एनीमिक) कथनों के वैध उपयोग हैं जिन्हें अन्य निर्माणों द्वारा पर्याप्त रूप से प्रतिस्थापित नहीं किया जा सकता है।
  4. बेशक, एक ही बयान के नाजायज उपयोग हैं।
  5. " godo" निरस्तीकरण जैसे आधुनिक नियंत्रण कथनों के गैर-नाजायज उपयोग भी हैं, जहां एक के स्थान पर doउपयोग करने से हमेशा एक गलत-झूठी लूप टूट जाता breakहै goto। ये अक्सर विवेकपूर्ण उपयोग से भी बदतर होते हैं goto

42
@pocjoc: उदाहरण के लिए, C में पूंछ-पुनरावर्ती अनुकूलन लिखना। यह कार्यात्मक भाषा दुभाषियों / रनटाइम के कार्यान्वयन में आता है, लेकिन समस्याओं की एक दिलचस्प श्रेणी का प्रतिनिधि है। सी में लिखे गए अधिकांश संकलक इसी कारण से गोटो का उपयोग करते हैं। इसका एक आला उपयोग जो ज्यादातर स्थितियों में नहीं होता है, बेशक, लेकिन जिन स्थितियों के लिए इसे बुलाया जाता है, वह उपयोग करने के लिए बहुत मायने रखता है।
zxq9

66
क्यों हर कोई दिक्क्स्ट्रा के "गोइंग टू हानिकारक" पेपर के बारे में बात करता है, नथुथ के जवाब का उल्लेख किए बिना, "स्टेटमेंट के साथ संरचित प्रोग्रामिंग"?
ओबलोमोव

22
@ नीत्शे-जो "यह एक निहायत धुरंधर पुआल आदमी है [...]" वह व्यंग्यात्मक रूप से एक झूठे द्वंद्व का उपयोग करके दिखा रहा है कि कलंक क्यों अतार्किक है। स्ट्रॉमन एक तार्किक गिरावट है जहां आप जानबूझकर विरोधी की स्थिति को गलत तरीके से पेश करते हैं जिससे यह पता चलता है कि उनकी स्थिति आसानी से हार गई है। उदा "नास्तिक सिर्फ नास्तिक हैं क्योंकि वे भगवान से नफरत करते हैं"। जब आप विपरीत चरम को सही मान लेते हैं तो एक गलत द्वंद्वात्मकता तब होती है जब कम से कम एक अतिरिक्त संभावना मौजूद होती है (यानी ब्लैक एंड व्हाइट)। उदाहरण के लिए "भगवान समलैंगिकों से नफरत करता है, इसलिए वह हेटेरोस से प्यार करता है।"
ब्रैडेन बेस्ट

27
@JLRishe आप बहुत गहराई से कुछ पढ़ रहे हैं जो वहां भी नहीं है। यह केवल एक सच्ची तार्किक पतनशीलता है यदि जो व्यक्ति ईमानदारी से इसका उपयोग करता है वह इसे तार्किक अर्थ बनाता है। लेकिन उन्होंने कहा कि यह व्यंग्यात्मक रूप से, स्पष्ट रूप से इंगित करता है कि वह जानता है कि यह हास्यास्पद है, और यह है कि वह इसे कैसे दिखा रहा है। वह "अपनी बात को सही ठहराने के लिए इसका उपयोग नहीं कर रहा है"; वह यह दिखाने के लिए इसका उपयोग कर रहा है कि यह कहना हास्यास्पद है कि गोटोस स्वचालित रूप से स्पेगेटी में कोड बनाता है। यानी आप अब भी गोटो के बिना शिट्टी कोड लिख सकते हैं। यह उसकी बात है और व्यंग्यात्मक मिथ्या द्वंद्ववाद उसे हास्यपूर्ण तरीके से चित्रित करने की उसकी विधि है।
ब्रैडेन बेस्ट

32
-1 एक बहुत बड़ा तर्क देने के लिए कि दिज्कस्ट्रा की टिप्पणी क्यों लागू नहीं होती है, यह बताना भूल जाते हैं कि gotoवास्तव में क्या फायदे हैं (जो कि सवाल पोस्ट किया गया है)
Maarten Bodewes

154

सर्वोत्तम प्रथाओं का आँख बंद करके पालन करना सर्वोत्तम अभ्यास नहीं है। gotoकिसी के प्रवाह नियंत्रण के रूप में बयानों से बचने का विचार अपठनीय स्पेगेटी कोड के उत्पादन से बचने के लिए है। यदि सही स्थानों पर संयम से उपयोग किया जाता है, तो वे कभी-कभी किसी विचार को व्यक्त करने का सबसे सरल, स्पष्ट तरीका हो सकते हैं। Zortech C ++ कंपाइलर और D प्रोग्रामिंग लैंग्वेज के निर्माता वाल्टर ब्राइट उन्हें अक्सर इस्तेमाल करते हैं, लेकिन विवेकपूर्ण तरीके से। यहां तक ​​कि gotoबयानों के साथ , उनका कोड अभी भी पूरी तरह से पठनीय है।

नीचे की रेखा: परहेज के gotoलिए टालना gotoव्यर्थ है। क्या आप वास्तव में बचना चाहते हैं अपठनीय कोड का उत्पादन कर रहा है। यदि आपका goto-laden कोड पठनीय है, तो इसमें कुछ भी गलत नहीं है।


36

चूंकि gotoप्रोग्राम फ्लो 1 (उर्फ "स्पेगेटी कोड") के बारे में तर्क देता है , gotoआमतौर पर इसका उपयोग केवल गुम सुविधाओं की भरपाई करने के लिए किया जाता है: gotoवास्तव में इसका उपयोग स्वीकार्य हो सकता है, लेकिन केवल अगर भाषा प्राप्त करने के लिए अधिक संरचित संस्करण की पेशकश नहीं करता है। एक ही लक्ष्य। संदेह का उदाहरण लें:

गोटो के साथ जो नियम हम उपयोग करते हैं वह यह है कि गोटो एक फ़ंक्शन में एकल निकास निकास बिंदु पर आगे कूदने के लिए ठीक है।

यह सच है - लेकिन केवल अगर भाषा सफाई कोड (जैसे RAII या finally) के साथ संरचित अपवाद को संभालने की अनुमति नहीं देती है , जो समान कार्य को बेहतर तरीके से करता है (जैसा कि यह विशेष रूप से इसे करने के लिए बनाया गया है), या जब कोई अच्छा कारण नहीं है संरचित अपवाद हैंडलिंग को नियोजित करने के लिए (लेकिन आपके पास यह मामला कभी नहीं होगा सिवाय बहुत निम्न स्तर पर)।

अधिकांश अन्य भाषाओं में, gotoनेस्टेड लूप से बाहर निकलने का एकमात्र स्वीकार्य उपयोग है। और यहां तक ​​कि बाहरी लूप को अपने तरीके से उठाने और returnइसके बजाय उपयोग करने के लिए लगभग हमेशा बेहतर होता है ।

इसके अलावा, gotoयह एक संकेत है कि पर्याप्त विचार कोड के विशेष टुकड़े में नहीं गया है।


1 आधुनिक भाषाएं जो gotoकुछ प्रतिबंधों को लागू करने का समर्थन करती हैं (जैसे gotoकि कार्यों में कूद या बाहर नहीं हो सकती हैं) लेकिन समस्या मौलिक रूप से समान है।

संयोग से, वही अन्य भाषा सुविधाओं के लिए भी सच है, सबसे विशेष रूप से अपवाद हैं। और आमतौर पर इन नियमों का उपयोग करने के लिए जगह में सख्त नियम हैं जहां संकेत दिया गया है, जैसे कि नियम गैर-असाधारण कार्यक्रम प्रवाह को नियंत्रित करने के लिए अपवादों का उपयोग नहीं करना।


4
बस यहाँ उत्सुक है, लेकिन सफाई कोड के लिए गोटो का उपयोग करने के मामले के बारे में क्या। साफ-सफाई से मेरा मतलब है, न केवल स्मृति का बहिष्कार, बल्कि त्रुटि, लॉगिंग भी कहते हैं। मैं पदों के एक समूह के माध्यम से पढ़ रहा था, और जाहिरा तौर पर, कोई भी कोड नहीं लिखता है जो प्रिंटों को लॉग करता है .. हम्म ?!
शिवा

37
"मूल रूप से, गोटो के दोषपूर्ण स्वभाव के कारण (और मेरा मानना ​​है कि यह निर्विवाद है)" -1 और मैंने वहां पढ़ना बंद कर दिया।
ओ ० '।

14
गोटो के खिलाफ तर्क संरचित प्रोग्रामिंग युग से आता है, जहां शुरुआती रिटर्न को भी बुराई माना जाता था। नेस्टेड लूप्स को एक फंक्शन में ले जाने से दूसरे के लिए एक "बुराई" का व्यापार होता है, और एक ऐसा फंक्शन बनाता है जिसका कोई वास्तविक कारण नहीं होता है ("इसके बाहर" ने मुझे गोटो का उपयोग करने से बचने की अनुमति दी है)। यह सच है कि अगर कोई बाधा नहीं है, तो गोटो स्पेगेटी कोड के उत्पादन के लिए सबसे शक्तिशाली उपकरण है, लेकिन यह इसके लिए एक आदर्श अनुप्रयोग है; यह कोड को सरल करता है। नुथ ने इस उपयोग के लिए तर्क दिया, और डेज्स्ट्रा ने कहा कि "यह विश्वास करने के जाल में मत पड़ो कि मैं गोटो के बारे में बहुत अधिक हठधर्मी हूं"।
मुदित

5
finally? तो त्रुटि से निपटने के अलावा अन्य चीजों के लिए अपवाद का उपयोग करना अच्छा है लेकिन उपयोग gotoकरना बुरा है? मुझे लगता है कि अपवाद काफी उपयुक्त हैं।
ईसाई

3
@Mud: मामलों है कि मैं (एक दैनिक आधार पर) मुठभेड़, एक समारोह "अस्तित्व के लिए कोई वास्तविक कारण है कि" बनाने में है सबसे अच्छा समाधान। कारण: यह शीर्ष-स्तरीय फ़ंक्शन से विस्तार को हटा देता है, जैसे कि परिणाम में आसानी से पढ़ने वाला नियंत्रण प्रवाह होता है। मैं व्यक्तिगत रूप से उन स्थितियों का सामना नहीं करता हूं जहां एक गोटो सबसे पठनीय कोड का उत्पादन करता है। दूसरी ओर, मैं साधारण कार्यों में कई रिटर्न का उपयोग करता हूं, जहां कोई व्यक्ति किसी एकल निकास बिंदु के लिए पसंद कर सकता है। मैं काउंटर-उदाहरणों को देखना पसंद करूंगा जहां गोटो अच्छी तरह से नामित कार्यों को फिर से शुरू करने की तुलना में अधिक पठनीय है।
टूलमेकरस्टेव

35

खैर, एक बात है जो हमेशा से बदतर है goto's; गोटो से बचने के लिए अन्य प्रोग्रामफ्लो ऑपरेटरों का अजीब उपयोग:

उदाहरण:

    // 1
    try{
      ...
      throw NoErrorException;
      ...
    } catch (const NoErrorException& noe){
      // This is the worst
    } 


    // 2
    do {
      ...break; 
      ...break;
    } while (false);


    // 3
    for(int i = 0;...) { 
      bool restartOuter = false;
      for (int j = 0;...) {
        if (...)
          restartOuter = true;
      if (restartOuter) {
        i = -1;
      }
    }

etc
etc

2
do{}while(false)मुझे लगता है कि मुहावरेदार माना जा सकता है। आपको असहमत होने की अनुमति नहीं है: डी
थॉमस

37
@trinithis: यदि यह "मुहावरेदार" है, तो यह केवल विरोधी गोटो पंथ के कारण है। यदि आप इसे करीब से देखते हैं, तो आपको एहसास होगा कि यह goto after_do_block;वास्तव में कहने के बिना कहने का एक तरीका है। अन्यथा ... एक "लूप" जो बिल्कुल एक बार चलता है? मुझे लगता है कि नियंत्रण संरचनाओं का दुरुपयोग होगा।
cHao

5
@ThomasEding Eding आपकी बात का एक अपवाद है। यदि आपने कभी कुछ C / C ++ प्रोग्रामिंग की है और आपको #define का उपयोग करना था, तो आपको पता होगा, कि {} जबकि (0) कोड की कई लाइनों को एनकैप्सुलेट करने के मानकों में से एक है। उदाहरण के लिए: #define do {memcpy (ए, बी, 1); कुछ ++;} जबकि (0) सुरक्षित और #define मेम्कपी
इग्नास 2526

10
@ इग्नास २५२६ आपने बहुत अच्छी तरह से दिखाया है कि कैसे #defineकई होते हैं, कई बार gotoएक समय में एक बार उपयोग करने की तुलना में बहुत बुरा होता है : डी
लुआं

3
+1 उन तरीकों की एक अच्छी सूची के लिए जो लोग गोटो से बचने की कोशिश करते हैं, एक चरम तक; मैंने ऐसी तकनीकों का उल्लेख कहीं और देखा है, लेकिन यह एक शानदार, संक्षिप्त, सूची है। क्यों, पिछले 15 वर्षों में, मेरी टीम को उन तकनीकों में से किसी की भी आवश्यकता नहीं है, और न ही गोटो का उपयोग किया गया है। यहां तक ​​कि कई प्रोग्रामर द्वारा कोड के हजारों लाइनों के साथ एक क्लाइंट / सर्वर एप्लिकेशन में। सी #, जावा, पीएचपी, अजगर, जावास्क्रिप्ट। क्लाइंट, सर्वर और ऐप कोड। डींग मारने और न ही एक स्थिति के लिए मुकदमा चलाने के लिए, बस वास्तव में जिज्ञासु क्यों कुछ लोग ऐसी परिस्थितियों का सामना करते हैं जो गोटोस के लिए सबसे स्पष्ट समाधान के रूप में भीख मांगते हैं, और अन्य नहीं ...
टूलमेकरसैट

28

में सी # स्विच बयान करता है वह अनुमति नहीं गिरावट के माध्यम से । तो एक विशिष्ट स्विच-केस लेबल या डिफ़ॉल्ट लेबल पर नियंत्रण स्थानांतरित करने के लिए गोटो का उपयोग किया जाता है ।

उदाहरण के लिए:

switch(value)
{
  case 0:
    Console.Writeln("In case 0");
    goto case 1;
  case 1:
    Console.Writeln("In case 1");
    goto case 2;
  case 2:
    Console.Writeln("In case 2");
    goto default;
  default:
    Console.Writeln("In default");
    break;
}

संपादित करें: "नो फॉल-थ्रू" नियम पर एक अपवाद है। यदि केस स्टेटमेंट में कोई कोड नहीं है, तो फॉल-थ्रू की अनुमति है।


3
स्विच फॉल-थ्रू .NET 2.0 में समर्थित है - msdn.microsoft.com/en-us/library/06tc147t(VS.80).aspx
rjzii

9
केवल अगर केस में कोड बॉडी नहीं है। यदि इसमें कोड है तो आपको गोटो कीवर्ड का उपयोग करना होगा।
मैथ्यू Whited

26
यह उत्तर बहुत मज़ेदार है - C # हटाए गए फ़ॉल-थ्रू क्योंकि बहुत से लोग इसे हानिकारक मानते हैं, और यह उदाहरण मूल को पुनर्जीवित करने के लिए गोटो (भी कई के द्वारा हानिकारक माना जाता है) का उपयोग करता है, माना जाता है कि हानिकारक, व्यवहार, लेकिन समग्र परिणाम वास्तव में कम हानिकारक है ( क्योंकि कोड यह स्पष्ट करता है कि गिरावट जानबूझकर है!)।
थोमसट्रेटर

9
सिर्फ इसलिए कि कोई कीवर्ड अक्षरों के साथ लिखा गया है GOTO इसे गोटो नहीं बनाता है। यह प्रस्तुत मामला कोई गोटो नहीं है। यह गिरावट के लिए एक स्विच स्टेटमेंट कंस्ट्रक्शन है। तो फिर, मैं वास्तव में सी # बहुत अच्छी तरह से नहीं जानता, इसलिए मैं गलत हो सकता हूं।
थॉमस एडिंग

1
खैर, इस मामले में यह गिरावट के माध्यम से थोड़ा अधिक है (क्योंकि आप कह सकते हैं कि goto case 5:जब आप केस 1 में होते हैं)। ऐसा लगता है कि कोनराड रूडोल्फ का उत्तर यहां सही है: gotoएक लापता सुविधा के लिए क्षतिपूर्ति कर रहा है (और वास्तविक सुविधा की तुलना में कम स्पष्ट है)। अगर हम वास्तव में चाहते हैं कि पतन-थ्रू हो, तो शायद सबसे अच्छा डिफ़ॉल्ट कोई फ़ॉल-थ्रू नहीं होगा, लेकिन continueयह स्पष्ट रूप से अनुरोध करना पसंद करता है।
डेविड स्टोन

14

#ifdef TONGUE_IN_CHEEK

पर्ल के पास एक gotoऐसा तरीका है जो आपको गरीब-आदमी की पूंछ कॉल को लागू करने की अनुमति देता है। :-P

sub factorial {
    my ($n, $acc) = (@_, 1);
    return $acc if $n < 1;
    @_ = ($n - 1, $acc * $n);
    goto &factorial;
}

#endif

ठीक है, ताकि सी के साथ कुछ नहीं करना है goto। अधिक गंभीरता से, मैं gotoक्लीनअप के लिए उपयोग करने के बारे में , या डफ के उपकरण को लागू करने के लिए , या इस तरह की अन्य टिप्पणियों से सहमत हूं । यह प्रयोग करने के बारे में है, न कि अपमानजनक।

(एक ही टिप्पणी लागू हो सकती है longjmp, अपवाद, call/ccऔर जैसे --- उनके वैध उपयोग हैं, लेकिन आसानी से दुरुपयोग किया जा सकता है। उदाहरण के लिए, पूरी तरह से गैर-असाधारण परिस्थितियों में, एक गहरी-नेस्टेड नियंत्रण संरचना से बचने के लिए विशुद्ध रूप से अपवाद को फेंकना। ।)


मुझे लगता है कि यह पर्ल में गोटो का उपयोग करने का एकमात्र कारण है।
ब्रैड गिल्बर्ट

12

मैंने वर्षों में विधानसभा भाषा की कुछ पंक्तियों से अधिक लिखा है। अंतत: प्रत्येक उच्च स्तरीय भाषा गोटो को संकलित करती है। ठीक है, उन्हें "शाखाएं" या "छलांग" कहें या जो कुछ भी हो, लेकिन वे गोटो हैं। क्या कोई गोटो-कम कोडांतरक लिख सकता है?

अब यकीन है, आप एक फोरट्रान, सी या बेसिक प्रोग्रामर को इंगित कर सकते हैं कि गोटो के साथ दंगा चलाने के लिए स्पेगेटी बोलोग्नाइस के लिए एक नुस्खा है। हालाँकि इसका उत्तर उन्हें टालना नहीं है, बल्कि उनका सावधानीपूर्वक उपयोग करना है।

चाकू का उपयोग भोजन तैयार करने, किसी को मुक्त करने या किसी को मारने के लिए किया जा सकता है। क्या हम बाद के डर के माध्यम से चाकू के बिना करते हैं? इसी तरह गोटो: लापरवाही से इस्तेमाल किया जाता है, यह सावधानीपूर्वक उपयोग किया जाता है।


1
शायद आप को पढ़ने के लिए क्यों मेरा मानना है कि इस पर मौलिक रूप से गलत है चाहता हूँ stackoverflow.com/questions/46586/...
कोनराड रूडोल्फ

15
किसी को भी, जो आगे "यह सब वैसे भी JMP के लिए नीचे संकलन!" तर्क मूल रूप से उच्च स्तरीय भाषा में प्रोग्रामिंग के पीछे की बात को नहीं समझता है।
नीत्शे-जौ

7
आप सभी की जरूरत है घटाव और शाखा है। बाकी सब कुछ सुविधा या प्रदर्शन के लिए है।
डेविड स्टोन

8

जब सी में प्रोग्रामिंग गोटो का उपयोग करने के लिए पर एक नज़र डालें :

यद्यपि गोटो का उपयोग लगभग हमेशा खराब प्रोग्रामिंग अभ्यास है (निश्चित रूप से आप XYZ करने का एक बेहतर तरीका पा सकते हैं), ऐसे समय होते हैं जब यह वास्तव में एक बुरा विकल्प नहीं होता है। कुछ लोग यह भी तर्क दे सकते हैं कि जब यह उपयोगी है, तो यह सबसे अच्छा विकल्प है।

गोटो के बारे में मुझे जो कहना है, उनमें से अधिकांश वास्तव में केवल सी पर लागू होता है। यदि आप सी ++ का उपयोग कर रहे हैं, तो अपवादों के स्थान पर गोटो का उपयोग करने का कोई ध्वनि कारण नहीं है। सी में, हालांकि, आपके पास अपवाद हैंडलिंग तंत्र की शक्ति नहीं है, इसलिए यदि आप अपने प्रोग्राम लॉजिक के बाकी हिस्सों से त्रुटि हैंडलिंग को अलग करना चाहते हैं, और आप अपने कोड में कई बार कोड को फिर से साफ करने से बचना चाहते हैं, फिर गोटो एक अच्छा विकल्प हो सकता है।

मेरा क्या मतलब है? आपके पास कुछ ऐसा कोड हो सकता है जो इस तरह दिखता है:

int big_function()
{
    /* do some work */
    if([error])
    {
        /* clean up*/
        return [error];
    }
    /* do some more work */
    if([error])
    {
        /* clean up*/
        return [error];
    }
    /* do some more work */
    if([error])
    {
        /* clean up*/
        return [error];
    }
    /* do some more work */
    if([error])
    {
        /* clean up*/
        return [error];
    }
    /* clean up*/
    return [success];
}

यह तब तक ठीक है जब तक आपको एहसास न हो कि आपको अपना सफाई कोड बदलने की आवश्यकता है। फिर आपको 4 बदलावों से गुजरना होगा। अब, आप यह तय कर सकते हैं कि आप केवल एक ही फ़ंक्शन में सभी क्लीनअप को इनकैप्सुलेट कर सकते हैं; यह एक बुरा विचार नहीं है। लेकिन इसका मतलब यह है कि आपको पॉइंटर्स से सावधान रहने की आवश्यकता होगी - यदि आप अपने क्लीनअप फ़ंक्शन में एक पॉइंटर को मुक्त करने की योजना बनाते हैं, तो इसे तब तक सेट करने का कोई तरीका नहीं है जब तक कि आप पॉइंटर में एक पॉइंटर में पास न हों। बहुत सारे मामलों में, आप वैसे भी उस पॉइंटर का फिर से उपयोग नहीं करेंगे, ताकि कोई बड़ी चिंता न हो। दूसरी ओर, यदि आप एक नए पॉइंटर, फ़ाइल हैंडल, या अन्य चीज़ को जोड़ते हैं, जिसमें सफाई की आवश्यकता होती है, तो आपको अपना सफाई कार्य फिर से बदलना होगा; और फिर आपको उस फ़ंक्शन के तर्कों को बदलना होगा।

का उपयोग करके goto, यह होगा

int big_function()
{
    int ret_val = [success];
    /* do some work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
end:
    /* clean up*/
    return ret_val;
}

यहाँ लाभ यह है कि आपके कोड के अंत में सब कुछ तक पहुँच होती है, जिसे सफाई की आवश्यकता होती है, और आपने परिवर्तन बिंदुओं की संख्या को काफी कम कर दिया है। एक और लाभ यह है कि आप अपने फ़ंक्शन के लिए कई निकास बिंदुओं से सिर्फ एक तक गए हैं; कोई मौका नहीं है कि आप गलती से सफाई के बिना फ़ंक्शन से वापस आ जाएंगे।

इसके अलावा, चूंकि गोटो का उपयोग केवल एक बिंदु पर कूदने के लिए किया जा रहा है, ऐसा नहीं है क्योंकि आप स्पैगेटी कोड का एक समूह बना रहे हैं जो फ़ंक्शन कॉल को अनुकरण करने के प्रयास में आगे और पीछे कूद रहा है। बल्कि, गोटो वास्तव में अधिक संरचित कोड लिखने में मदद करता है।


एक शब्द में, gotoहमेशा संयम से और अंतिम उपाय के रूप में इस्तेमाल किया जाना चाहिए - लेकिन इसके लिए एक समय और एक जगह है। सवाल यह नहीं होना चाहिए "क्या आपको इसका उपयोग करना है" लेकिन इसका उपयोग करने के लिए "यह सबसे अच्छा विकल्प है"।


7

गोटो खराब होने के कारणों में से एक कोडिंग स्टाइल के अलावा यह भी है कि आप इसका इस्तेमाल ओवरलैपिंग बनाने के लिए कर सकते हैं , लेकिन नॉन-नेस्टेड लूप्स:

loop1:
  a
loop2:
  b
  if(cond1) goto loop1
  c
  if(cond2) goto loop2

यह विचित्र, लेकिन संभवतः कानूनी प्रवाह-नियंत्रण संरचना का निर्माण करेगा, जहां (ए, बी, सी, बी, ए, बी, ए, बी, ...) जैसे अनुक्रम संभव है, जो संकलक हैकर्स को दुखी करता है। जाहिरा तौर पर इस तरह के ढांचे पर भरोसा करने वाले कई चतुर अनुकूलन चालें हैं जो नहीं करते हैं। (मुझे ड्रैगन बुक की अपनी कॉपी की जांच करनी चाहिए ...) इसका परिणाम यह हो सकता है (कुछ संकलक का उपयोग करके) यह हो सकता है कि कोड के लिए अन्य अनुकूलन नहीं किए गए हैं जिनमें gotoएस शामिल हैं ।

यह उपयोगी हो सकता है यदि आप इसे जानते हैं, "ओह, वैसे", कंपाइलर को तेजी से कोड का उत्सर्जन करने के लिए मनाने के लिए होता है। व्यक्तिगत रूप से, मैं संकलक को समझाने की कोशिश करना पसंद करूंगा कि क्या संभावित है और गोटो जैसी चाल का उपयोग करने से पहले क्या नहीं है, लेकिन यकीनन, मैं भी gotoकोडांतरक को हैक करने से पहले कोशिश कर सकता हूं ।


3
खैर ... मुझे एक वित्तीय सूचना कंपनी में प्रोग्रामिंग फोरट्रान के दिनों में वापस ले जाता है। 2007 में।
मार्सिन

5
किसी भी भाषा संरचना को उन तरीकों से दुरुपयोग किया जा सकता है जो इसे अपठनीय या खराब प्रदर्शन करते हैं।
बस मेरा सही चुनाव

@ जस्ट: बिंदु पठनीयता या खराब प्रदर्शन के बारे में नहीं है, लेकिन प्रवाह के नियंत्रण ग्राफ के बारे में मान्यताओं और गारंटी है। गोटो का कोई भी दुरुपयोग बढ़े हुए प्रदर्शन (या पठनीयता) के लिए होगा।
एंडर्स यूरेनियस

3
मेरा तर्क है कि कारणों में से gotoएक उपयोगी है कि यह आपको इस तरह से छोरों का निर्माण करने की अनुमति देता है, इसके लिए अन्यथा तार्किक विरोधाभासों की एक गुच्छा की आवश्यकता होगी। मैं आगे यह तर्क दूंगा कि यदि ऑप्टिमाइज़र यह नहीं जानता कि यह कैसे फिर से लिखना है, तो अच्छा है । इस तरह एक लूप प्रदर्शन या पठनीयता के लिए नहीं किया जाना चाहिए, लेकिन क्योंकि यह ठीक उसी क्रम में है जिसमें चीजें होने की आवश्यकता होती है। जिस स्थिति में मैं विशेष रूप से नहीं चाहूंगा कि आशावादी इसके साथ पंगा ले।
cHao

1
... गोटो आधारित कोड में आवश्यक एल्गोरिथ्म का सीधा अनुवाद ध्वज चर की गड़बड़ी और दुर्व्यवहार लूपिंग निर्माणों की तुलना में मान्य करने के लिए बहुत आसान हो सकता है।
सुपरकैट

7

मुझे यह हास्यास्पद लगता है कि कुछ लोग उन मामलों की एक सूची देने के लिए जहाँ तक गोटो स्वीकार्य है, यह कहते हुए कि अन्य सभी उपयोग अस्वीकार्य हैं। क्या आप वास्तव में सोचते हैं कि आप हर मामले को जानते हैं कि गोटो एक एल्गोरिथ्म को व्यक्त करने के लिए सबसे अच्छा विकल्प कहां है?

वर्णन करने के लिए, मैं आपको एक उदाहरण दूंगा जिसे यहाँ किसी ने अभी तक नहीं दिखाया है:

आज मैं हैश तालिका में एक तत्व सम्मिलित करने के लिए कोड लिख रहा था। हैश टेबल पिछली गणनाओं का एक कैश होता है जिसे वसीयत में लिखा जा सकता है (प्रदर्शन को प्रभावित करता है लेकिन शुद्धता नहीं)।

हैश टेबल की प्रत्येक बाल्टी में 4 स्लॉट होते हैं, और मेरे पास यह तय करने के लिए मापदंड का एक गुच्छा होता है कि एक बाल्टी भर जाने पर कौन से तत्व को अधिलेखित करना है। अभी इसका मतलब एक बाल्टी के माध्यम से तीन पास करना है, जैसे:

// Overwrite an element with same hash key if it exists
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
  if (slot_p[add_index].hash_key == hash_key)
    goto add;

// Otherwise, find first empty element
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
  if ((slot_p[add_index].type == TT_ELEMENT_EMPTY)
    goto add;

// Additional passes go here...

add:
// element is written to the hash table here

अब अगर मैंने गोटो का उपयोग नहीं किया, तो यह कोड कैसा दिखेगा?

कुछ इस तरह:

// Overwrite an element with same hash key if it exists
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
  if (slot_p[add_index].hash_key == hash_key)
    break;

if (add_index >= ELEMENTS_PER_BUCKET) {
  // Otherwise, find first empty element
  for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
    if ((slot_p[add_index].type == TT_ELEMENT_EMPTY)
      break;
  if (add_index >= ELEMENTS_PER_BUCKET)
   // Additional passes go here (nested further)...
}

// element is written to the hash table here

यदि अधिक पास जोड़े जाते हैं तो यह और भी बुरा लगेगा, जबकि गोटो वाला संस्करण हर समय एक ही इंडेंटेशन स्तर रखता है और यदि स्टेटमेंट जिसका परिणाम पिछले लूप के निष्पादन द्वारा निहित है, तो स्पुरियस के उपयोग से बचा जाता है।

तो वहाँ एक और मामला है जहां गोटो कोड क्लीनर और लिखने और समझने में आसान बनाता है ... मुझे यकीन है कि कई और भी हैं, इसलिए उन सभी मामलों को जानने का नाटक न करें जहां गोटो उपयोगी है, किसी भी अच्छे को निष्क्रिय करना जो आप नहीं कर सकते 'का मत सोचो।


1
आपके द्वारा दिए गए उदाहरण में, मैं उस प्रतिक्षेपक को पसंद करना चाहूंगा जो बहुत महत्वपूर्ण है। सामान्य तौर पर, मैं एक-लाइनर टिप्पणियों से बचने की कोशिश करता हूं जो कहती हैं कि कोड का अगला हिस्सा क्या कर रहा है। इसके बजाय, मैं इसे अपने स्वयं के फ़ंक्शन में तोड़ देता हूं जिसे टिप्पणी के समान नाम दिया गया है। यदि आप ऐसा परिवर्तन करना चाहते थे, तो यह फ़ंक्शन उच्च स्तर का अवलोकन देगा कि फ़ंक्शन क्या कर रहा है, और प्रत्येक नए फ़ंक्शन में बताया जाएगा कि आप प्रत्येक चरण को कैसे करते हैं। मुझे लगता है कि gotoप्रत्येक फ़ंक्शन के अमूर्त स्तर पर होने से किसी भी विपक्ष की तुलना में बहुत अधिक महत्वपूर्ण है । इससे बचा जाता gotoहै कि यह एक बोनस है।
डेविड स्टोन

2
आपने वास्तव में यह नहीं बताया है कि कैसे अधिक कार्यों को जोड़ने से गोटो से छुटकारा मिल जाता है, कई इंडेंटेशन के स्तर और अगर बयान दिए गए हैं ...
रिकार्डो

यह मानक कंटेनर संकेतन का उपयोग करते हुए कुछ इस तरह दिखाई देगा: container::iterator it = slot_p.find(hash_key); if (it != slot_p.end()) it->overwrite(hash_key); else it = slot_p.find_first_empty();मुझे लगता है कि प्रोग्रामिंग को पढ़ने में बहुत आसान है। इस मामले में प्रत्येक फ़ंक्शन को शुद्ध फ़ंक्शन के रूप में लिखा जा सकता है, जिसके बारे में तर्क करना बहुत आसान है। मुख्य फ़ंक्शन अब बताता है कि फ़ंक्शन के नाम से कोड क्या करता है, और फिर यदि आप चाहें, तो आप यह पता लगाने के लिए उनकी परिभाषाओं को देख सकते हैं कि यह कैसे करता है।
डेविड स्टोन

3
तथ्य यह है कि किसी को भी उदाहरण देना है, कि कुछ एल्गोरिदम को स्वाभाविक रूप से एक गोटो का उपयोग कैसे करना चाहिए - एक दुखद प्रतिबिंब है कि आज कल कितनी छोटी एल्गोरिथ्म सोच चलती है !! बेशक, @ रिकार्डो का उदाहरण (कई में से एक) आदर्श उदाहरण है जहां गोटो सुरुचिपूर्ण और स्पष्ट है।
फेटी

6

गोटो के साथ जो नियम हम उपयोग करते हैं वह यह है कि गोटो एक फ़ंक्शन में एकल निकास निकास बिंदु पर आगे कूदने के लिए ठीक है। वास्तव में जटिल कार्यों में हम उस नियम को शिथिल करते हैं जिससे अन्य कूदने की अनुमति मिलती है। दोनों मामलों में हम गहराई से नेस्टेड कर रहे हैं यदि कथन जो अक्सर त्रुटि कोड की जाँच के साथ होते हैं, जो पठनीयता और रखरखाव में मदद करता है।


1
मैं सी जैसी भाषा में उपयोगी होने जैसा कुछ देख सकता हूं। हालांकि, जब आपके पास C ++ कंस्ट्रक्टर / डिस्ट्रक्टर्स की शक्ति है, तो यह आमतौर पर इतना उपयोगी नहीं है।
डेविड स्टोन

1
"वास्तव में जटिल कार्यों में हम आराम से कूदने की अनुमति देने के लिए उस नियम को शिथिल करते हैं" उदाहरण के बिना, ऐसा लगता है, अगर आप जंप का उपयोग करके जटिल कार्यों को और भी अधिक जटिल बना रहे हैं। रिफ्लेक्टर और उन जटिल कार्यों को विभाजित करने के लिए "बेहतर" दृष्टिकोण नहीं होगा?
माइक एमबी

1
यह अंतिम उद्देश्य था जिसके लिए मैंने गोटो का इस्तेमाल किया। मुझे जावा में गोटो याद नहीं है, क्योंकि इसमें कोशिश की जाती है कि वही काम कर सके।
पेट्रीसिया शहनान

5

गोटो बयानों का सबसे विचारशील और गहन चर्चा, उनके वैध उपयोग, और वैकल्पिक निर्माण जो "पुण्य गोटो बयानों" के स्थान पर इस्तेमाल किया जा सकता है, लेकिन गोटो बयानों के रूप में आसानी से दुरुपयोग किया जा सकता है, डोनाल्ड नुथ का लेख है " गोटो बयानों के साथ संरचना " , दिसंबर 1974 में सर्वेक्षण सर्वेक्षण (मात्रा 6, संख्या 4. पीपी 261 - 301)।

आश्चर्य की बात नहीं, इस 39 वर्षीय कागज के कुछ पहलुओं को दिनांकित किया गया है: प्रसंस्करण शक्ति में वृद्धि-दर-परिमाण में वृद्धि से नथ के प्रदर्शन में कुछ सुधार हो सकते हैं जो मामूली आकार की समस्याओं के लिए ध्यान देने योग्य हैं, और नए प्रोग्रामिंग-भाषा निर्माण का आविष्कार तब से किया गया है। (उदाहरण के लिए, ट्राई-कैच ब्लॉक ज़ैन के कंस्ट्रक्शन को कम करता है, हालांकि वे शायद ही कभी इस तरह से उपयोग किए जाते हैं।) लेकिन नुथ तर्क के सभी पक्षों को शामिल करते हैं, और किसी को भी इस मुद्दे को फिर से पेश करने से पहले पढ़ने की आवश्यकता होनी चाहिए।


3

एक पर्ल मॉड्यूल में, आप कभी-कभी फ्लाई पर सबरूटीन या क्लोजर बनाना चाहते हैं। बात यह है, कि एक बार जब आप सबरूटीन बना लेते हैं, तो आप इसे कैसे प्राप्त करते हैं। आप बस इसे कॉल कर सकते हैं, लेकिन फिर अगर सबरूटीन उपयोग करता है तो caller()यह उतना उपयोगी नहीं होगा जितना कि यह हो सकता है। यह वह जगह है जहाँ goto &subroutineभिन्नता सहायक हो सकती है।

यहाँ एक त्वरित उदाहरण है:

sub AUTOLOAD{
  my($self) = @_;
  my $name = $AUTOLOAD;
  $name =~ s/.*:://;

  *{$name} = my($sub) = sub{
    # the body of the closure
  }

  goto $sub;

  # nothing after the goto will ever be executed.
}

आप इस रूप का उपयोग gotoपूंछ-कॉल अनुकूलन के एक अल्पविकसित रूप प्रदान करने के लिए भी कर सकते हैं ।

sub factorial($){
  my($n,$tally) = (@_,1);

  return $tally if $n <= 1;

  $tally *= $n--;
  @_ = ($n,$tally);
  goto &factorial;
}

( पर्ल 5 संस्करण 16 में जो बेहतर लिखा जाएगा goto __SUB__;)

एक मॉड्यूल है जो एक tailसंशोधक आयात करेगा और एक आयात करेगा recurयदि आप इस फॉर्म का उपयोग करना पसंद नहीं करते हैं goto

use Sub::Call::Tail;
sub AUTOLOAD {
  ...
  tail &$sub( @_ );
}

use Sub::Call::Recur;
sub factorial($){
  my($n,$tally) = (@_,1);

  return $tally if $n <= 1;
  recur( $n-1, $tally * $n );
}

उपयोग करने के अन्य कारणों में से अधिकांश gotoअन्य खोजशब्दों के साथ बेहतर काम करते हैं।

redoकोड के एक बिट आईएनजी की तरह :

LABEL: ;
...
goto LABEL if $x;
{
  ...
  redo if $x;
}

या lastकई स्थानों से कोड के एक बिट में जा रहा है :

goto LABEL if $x;
...
goto LABEL if $y;
...
LABEL: ;
{
  last if $x;
  ...
  last if $y
  ...
}

2

यदि हां, तो क्यों?

C का कोई बहु-स्तरीय / लेबल विराम नहीं है, और सभी नियंत्रण प्रवाह को C की पुनरावृत्ति और निर्णय प्रधानता के साथ आसानी से मॉडल नहीं किया जा सकता है। गोटो इन दोषों के निवारण की दिशा में एक लंबा रास्ता तय करते हैं।

कभी-कभी किसी प्रकार के छद्म-बहु-स्तरीय ब्रेक को प्रभावित करने के लिए किसी प्रकार के ध्वज चर का उपयोग करना स्पष्ट होता है, लेकिन यह हमेशा गोटो से बेहतर नहीं होता है (कम से कम एक गोटो आसानी से यह निर्धारित करने की अनुमति देता है कि नियंत्रण एक ध्वज चर के विपरीत कहां जाता है ), और कभी-कभी आप गोटो से बचने के लिए झंडे / अन्य विरोधाभासों के प्रदर्शन मूल्य का भुगतान नहीं करना चाहते हैं।

libavcodec कोड का एक प्रदर्शन-संवेदनशील टुकड़ा है। नियंत्रण प्रवाह की प्रत्यक्ष अभिव्यक्ति शायद एक प्राथमिकता है, क्योंकि यह बेहतर तरीके से चलेगा।


2

बस के रूप में अच्छी तरह से कोई भी कभी भी "कम से कम" कथन को लागू किया ...।


8
या C ++, C #, Java, JS, Python, Ruby .... आदि आदि में। केवल वे इसे "अपवाद" कहते हैं।
cHao

2

मुझे पता है {} जबकि (झूठा) पूरी तरह से विद्रोह का उपयोग। यह बोधगम्य है मुझे समझा सकता है यह कुछ विषम मामले में आवश्यक है, लेकिन कभी भी यह साफ समझदार कोड नहीं है।

यदि आपको कुछ ऐसे लूप करने चाहिए, तो ध्वज चर पर निर्भरता को स्पष्ट क्यों न करें?

for (stepfailed=0 ; ! stepfailed ; /*empty*/)

ऐसा नहीं है कि चाहिए /*empty*/हो stepfailed = 1? किसी भी मामले में, यह एक से बेहतर कैसे है do{}while(0)? दोनों में, आपको breakइससे बाहर (या आप में stepfailed = 1; continue;) जरूरत है। मेरे लिए अनावश्यक लगता है।
थॉमस एडिंग

2

1) गोटो का सबसे आम उपयोग जो मुझे पता है कि उन भाषाओं में अपवाद से निपटने का अनुकरण है जो इसे प्रस्तुत नहीं करते हैं, अर्थात् सी। (ऊपर परमाणु द्वारा दिए गए कोड बस यही है।) लिनक्स स्रोत कोड को देखें और आप ' एक bazillion गोटो को इस तरह से इस्तेमाल करते देखेंगे; 2013 में किए गए एक त्वरित सर्वेक्षण के अनुसार लिनक्स कोड में लगभग 100,000 गोटो थे: http://blog.regehr.org/archives/894 । लिनक्स कोडिंग स्टाइल गाइड में भी गोटो के उपयोग का उल्लेख किया गया है: https://www.kernel.org/doc/Documentation/CodingStyle । जैसे ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग को फंक्शन पॉइंटर्स के साथ पॉपुलेटेड स्ट्रक्चर्स का उपयोग करके इम्यूलेट किया जाता है, वैसे ही C प्रोग्रामिंग में गोटो का स्थान है। तो कौन सही है: डजस्क्रा या लिनुस (और सभी लिनक्स कर्नेल कोडर्स)? यह मूल रूप से सिद्धांत बनाम अभ्यास है।

हालांकि, सामान्य निर्माण / पैटर्न के लिए संकलक-स्तर का समर्थन और जांच नहीं करने के लिए सामान्य रूप से गेटा है: उन्हें गलत उपयोग करना आसान है और संकलन-समय की जांच के बिना बग का परिचय देना है। विंडोज और विजुअल सी ++ लेकिन सी मोड में एसईएच / वीईएच के माध्यम से अपवाद हैंडलिंग की पेशकश इस कारण से: अपवाद ओओपी भाषाओं के बाहर भी उपयोगी हैं, अर्थात एक प्रक्रियात्मक भाषा में। लेकिन कंपाइलर हमेशा आपके बेकन को नहीं बचा सकता है, भले ही वह भाषा में अपवादों के लिए सिंटैक्टिक समर्थन प्रदान करता हो। बाद के मामले के उदाहरण पर विचार करें प्रसिद्ध Apple एसएसएल "गोटो फेल" बग, जिसने सिर्फ एक गोटो को विनाशकारी परिणामों के साथ दोहराया ( https://www.imperialviolet.org/2014/02/22/applebug.html ):

if (something())
  goto fail;
  goto fail; // copypasta bug
printf("Never reached\n");
fail:
  // control jumps here

आप संकलक-अपवादित अपवादों का उपयोग करके ठीक वैसा ही बग रख सकते हैं, जैसे C ++ में:

struct Fail {};

try {
  if (something())
    throw Fail();
    throw Fail(); // copypasta bug
  printf("Never reached\n");
}
catch (Fail&) {
  // control jumps here
}

लेकिन अगर कंपाइलर विश्लेषण करता है और अगम्य कोड के बारे में आपको चेतावनी देता है, तो बग के दोनों प्रकारों से बचा जा सकता है। उदाहरण के लिए / W4 चेतावनी स्तर पर Visual C ++ के साथ संकलन करने से दोनों मामलों में बग का पता चलता है। उदाहरण के लिए जावा एक बहुत अच्छे कारण के लिए अनुपलब्ध कोड को निषिद्ध करता है (जहां वह इसे पा सकता है!): यह औसत जो के कोड में एक बग होने की संभावना है। जब तक गोटो निर्माण लक्ष्य की अनुमति नहीं देता है कि कंपाइलर आसानी से पता नहीं लगा सकता है, जैसे गोटो को गणना किए गए पते (**) के लिए, यह कंपाइलर के लिए डिक्स्ट्रा का उपयोग करने की तुलना में गोटो के साथ एक फ़ंक्शन के अंदर पहुंच योग्य कोड खोजने के लिए कोई कठिन नहीं है। -प्राप्त कोड।

(**) फुटनोट: बेसिक के कुछ संस्करणों में गणना की गई संख्याओं के लिए गॉटोस संभव हैं, उदाहरण के लिए GOTO 10 * x जहां x एक चर है। भ्रामक रूप से, फोरट्रान में "कंप्यूटेड गोटो" एक निर्माण को संदर्भित करता है जो सी में एक स्विच स्टेटमेंट के बराबर होता है। मानक सी भाषा में गणना गोटो को अनुमति नहीं देता है, लेकिन केवल गोटो को सांख्यिकीय / वाक्यगत रूप से घोषित लेबल के लिए अनुमति देता है। GNU C में हालांकि एक लेबल (unary, उपसर्ग और& ऑपरेटर) का पता प्राप्त करने के लिए एक एक्सटेंशन है और एक गोटो को प्रकार शून्य के एक चर में अनुमति देता है। इस अस्पष्ट उप-विषय पर अधिक जानकारी के लिए https://gcc.gnu.org/oniltocs/gcc/Labels-as-Values.html देखें । इस पोस्ट के बाकी लोग उस अस्पष्ट GNU C फीचर से चिंतित नहीं हैं।

मानक सी (यानी गणना नहीं की गई) गोटो आमतौर पर यही कारण नहीं है कि संकलन समय पर अनुपलब्ध कोड नहीं मिल सकता है। सामान्य कारण निम्नलिखित की तरह तर्क कोड है। दिया हुआ

int computation1() {
  return 1;
}

int computation2() {
  return computation1();
}

यह कंपाइलर के लिए बस उतना ही कठिन है जितना कि निम्नलिखित 3 निर्माणों में से किसी में भी पहुंच योग्य नहीं है:

void tough1() {
  if (computation1() != computation2())
    printf("Unreachable\n");
}

void tough2() {
  if (computation1() == computation2())
    goto out;
  printf("Unreachable\n");
out:;
}

struct Out{};

void tough3() {
  try {
    if (computation1() == computation2())
      throw Out();
    printf("Unreachable\n");
  }
  catch (Out&) {
  }
}

(मेरी ब्रेस-संबंधी कोडिंग शैली को क्षमा करें, लेकिन मैंने उदाहरणों को यथासंभव कॉम्पैक्ट रखने की कोशिश की।)

विजुअल C ++ / W4 (यहां तक ​​कि / Ox के साथ) इनमें से किसी में भी पहुंच योग्य कोड खोजने में विफल रहता है, और जैसा कि आप शायद जानते हैं कि अगम्य कोड को खोजने की समस्या सामान्य रूप से अनिर्दिष्ट है। (यदि आप मेरे बारे में विश्वास नहीं करते हैं: https://www.cl.cam.ac.uk/teaching/2006/OptComp/slides/lecture02.pdf )

संबंधित मुद्दे के रूप में, सी गोटो का उपयोग केवल फ़ंक्शन के शरीर के अंदर अपवादों का अनुकरण करने के लिए किया जा सकता है। मानक सी लाइब्रेरी गैर-स्थानीय निकास / अपवादों के अनुकरण के लिए सेटजम्प () और लॉन्गजम्प () फ़ंक्शंस की जोड़ी प्रदान करती है, लेकिन अन्य भाषाओं की तुलना में इनमें कुछ गंभीर कमियां हैं। विकिपीडिया लेख http://en.wikipedia.org/wiki/Setjmp.h इस उत्तरार्द्ध मुद्दे को काफी अच्छी तरह से समझाता है। यह फ़ंक्शन जोड़ी विंडोज ( http://msdn.microsoft.com/en-us/library/yz2ez4as.aspx ) पर भी काम करती है , लेकिन शायद ही कोई उन्हें वहां इस्तेमाल करता हो क्योंकि SEH / VEH बेहतर है। यूनिक्स पर भी, मुझे लगता है कि सेटजम्प और लॉन्गजम्प बहुत ही कम उपयोग किए जाते हैं।

2) मुझे लगता है कि सी में गोटो का दूसरा सबसे आम उपयोग मल्टी-लेवल ब्रेक या मल्टी-लेवल जारी है, जो एक काफी अनियंत्रित उपयोग मामला है। याद रखें कि जावा गेटो लेबल की अनुमति नहीं देता है, लेकिन लेबल तोड़ने या लेबल जारी रखने की अनुमति देता है। Http://www.oracle.com/technetwork/java/simple-142616.html के अनुसार , यह वास्तव में सी में गोटो का सबसे आम उपयोग का मामला है (90% वे कहते हैं), लेकिन मेरे व्यक्तिपरक अनुभव में, सिस्टम कोड जाता है अधिक बार हैंडलिंग के लिए गोटो का उपयोग करना। शायद वैज्ञानिक कोड में या जहां ओएस अपवाद हैंडलिंग (विंडोज) प्रदान करता है तो बहु-स्तरीय निकास प्रमुख उपयोग के मामले हैं। वे वास्तव में अपने सर्वेक्षण के संदर्भ में कोई विवरण नहीं देते हैं।

जोड़ने के लिए संपादित: यह पता चलता है कि ये दो उपयोग पैटर्न कर्निघन और रिची की सी बुक में पाए जाते हैं, पृष्ठ 60 के आसपास (संस्करण पर निर्भर करता है)। नोट की एक और बात यह है कि दोनों उपयोग के मामलों में केवल आगे के गोटो शामिल हैं। और यह पता चला कि MISRA C 2012 संस्करण (2004 संस्करण के विपरीत) अब गोटो को अनुमति देता है, जब तक कि वे केवल आगे वाले होते हैं।


सही। "कमरे में हाथी" यह है कि लिनक्स कर्नेल, अच्छाई के लिए, विश्व-महत्वपूर्ण कोड आधार के एक उदाहरण के रूप में - गोटो से भरा हुआ है। निश्चित रूप से यह है। जाहिर है। "एंटी-गोटो-मेमे" दशकों पहले से ही एक जिज्ञासा है। पाठ्यक्रम में, प्रोग्रामिंग में कई चीजें हैं (विशेष रूप से "स्टेटिक्स", वास्तव में "ग्लोबल्स" और उदाहरण के लिए "पर्सिफ़") जो गैर-पेशेवरों द्वारा दुरुपयोग किया जा सकता है। इसलिए, यदि आप बच्चे के चचेरे भाई हैं, तो 2 कार्यक्रम सीखें, आप उन्हें बताएं कि "ओह ग्लोबल्स का उपयोग न करें" और "कभी भी अन्य का उपयोग न करें"।
फेटी

गोटो फेल बग का गोटो से कोई लेना-देना नहीं है। समस्या बिना ब्रेसिज़ के बाद के बयान के कारण होती है। बस किसी भी स्टेटमेंट कॉपी के बारे में दो बार चिपकाए जाने से समस्या खड़ी हो जाती। मुझे लगता है कि नग्न ब्रासेलेस का प्रकार यदि गोटो से बहुत अधिक हानिकारक है।
मुसबोल्ला 20

2

कुछ का कहना है कि C ++ में गोटो का कोई कारण नहीं है। कुछ कहते हैं कि 99% मामलों में बेहतर विकल्प हैं। यह तर्कपूर्ण नहीं है, सिर्फ तर्कहीन छाप है। यहाँ एक ठोस उदाहरण है जहाँ गोटो एक अच्छे कोड की ओर ले जाता है, कुछ ऐसा है जैसे बढ़ा हुआ लूप।

int i;

PROMPT_INSERT_NUMBER:
  std::cout << "insert number: ";
  std::cin >> i;
  if(std::cin.fail()) {
    std::cin.clear();
    std::cin.ignore(1000,'\n');
    goto PROMPT_INSERT_NUMBER;          
  }

std::cout << "your number is " << i;

इसे गोटो-फ्री कोड से तुलना करें:

int i;

bool loop;
do {
  loop = false;
  std::cout << "insert number: ";
  std::cin >> i;
  if(std::cin.fail()) {
    std::cin.clear();
    std::cin.ignore(1000,'\n');
    loop = true;          
  }
} while(loop);

std::cout << "your number is " << i;

मुझे ये अंतर दिखाई देते हैं:

  • नेस्टेड {}ब्लॉक की जरूरत है (यद्यपि do {...} whileअधिक परिचित लग रहा है)
  • अतिरिक्त loopचर की जरूरत है, चार स्थानों पर उपयोग किया जाता है
  • इसके साथ काम को पढ़ने और समझने में अधिक समय लगता है loop
  • loopकिसी भी डेटा नहीं रखता है, यह सिर्फ निष्पादन के प्रवाह है, जो सरल लेबल से भी कम समय सुबोध है को नियंत्रित करता है

एक और उदाहरण है

void sort(int* array, int length) {
SORT:
  for(int i=0; i<length-1; ++i) if(array[i]>array[i+1]) {
    swap(data[i], data[i+1]);
    goto SORT; // it is very easy to understand this code, right?
  }
}

अब "दुष्ट" गोटो से छुटकारा पाएं:

void sort(int* array, int length) {
  bool seemslegit;
  do {
    seemslegit = true;
    for(int i=0; i<length-1; ++i) if(array[i]>array[i+1]) {
      swap(data[i], data[i+1]);
      seemslegit = false;
    }
  } while(!seemslegit);
}

आप देखते हैं कि यह गोटो का उपयोग करने का एक ही प्रकार है, यह अच्छी तरह से संरचित पैटर्न है और यह केवल उतने ही प्रमोशनल गोटो के रूप में प्रचारित नहीं है। निश्चित रूप से आप इस तरह "स्मार्ट" कोड से बचना चाहते हैं:

void sort(int* array, int length) {
  for(int i=0; i<length-1; ++i) if(array[i]>array[i+1]) {
    swap(data[i], data[i+1]);
    i = -1; // it works, but WTF on the first glance
  }
}

मुद्दा यह है कि गोटो का आसानी से दुरुपयोग किया जा सकता है, लेकिन गोटो को ही दोष नहीं देना है। ध्यान दें कि लेबल में C ++ में फंक्शन स्कोप है, इसलिए यह शुद्ध असेंबली की तरह ग्लोबल स्कोप को प्रदूषित नहीं करता है, जिसमें ओवरलैपिंग लूप्स में अपनी जगह होती है और 8051 के लिए निम्न कोड की तरह होते हैं, जहां 7 डिसप्ले डिस्प्ले P1 से जुड़ा होता है। इस कार्यक्रम के चारों ओर बिजली की धारा लूप:

; P1 states loops
; 11111110 <-
; 11111101  |
; 11111011  |
; 11110111  |
; 11101111  |
; 11011111  |
; |_________|

init_roll_state:
    MOV P1,#11111110b
    ACALL delay
next_roll_state:
    MOV A,P1
    RL A
    MOV P1,A
    ACALL delay
    JNB P1.5, init_roll_state
    SJMP next_roll_state

एक और फायदा है: गोटो नामित छोरों, स्थितियों और अन्य प्रवाह के रूप में काम कर सकता है:

if(valid) {
  do { // while(loop)

// more than one page of code here
// so it is better to comment the meaning
// of the corresponding curly bracket

  } while(loop);
} // if(valid)

या आप इंडेंटेशन के साथ समतुल्य गोटो का उपयोग कर सकते हैं, इसलिए आपको लेबल नाम का चयन बुद्धिमानी से करने की आवश्यकता नहीं है:

if(!valid) goto NOTVALID;
  LOOPBACK:

// more than one page of code here

  if(loop) goto LOOPBACK;
NOTVALID:;

1

पर्ल में, "गोटो" के लिए एक लूप से एक लेबल का उपयोग - एक "अंतिम" स्टेटमेंट का उपयोग करना, जो कि ब्रेक के समान है।

यह नेस्टेड छोरों पर बेहतर नियंत्रण की अनुमति देता है।

पारंपरिक गोटो लेबल का भी समर्थन किया जाता है, लेकिन मुझे यकीन नहीं है कि बहुत सारे उदाहरण हैं जहां आप जो चाहते हैं उसे प्राप्त करने का एकमात्र तरीका है - सबरूटीन्स और लूप अधिकांश मामलों के लिए पर्याप्त होना चाहिए।


मुझे लगता है कि गोटो का एकमात्र रूप है जिसे आप कभी पर्ल में उपयोग करेंगे goto &subroutine। जो स्टैक में करंट सबरूटीन को रिप्लेस करते हुए करंट @_ के साथ सबरूटीन को शुरू करता है।
ब्रैड गिल्बर्ट

1

'गोटो' के साथ समस्या और 'गोटो-लेस प्रोग्रामिंग' मूवमेंट का सबसे महत्वपूर्ण तर्क यह है कि यदि आप इसका उपयोग अक्सर अपने कोड में करते हैं, हालांकि यह सही ढंग से व्यवहार कर सकता है, 99.99% में अपठनीय, अप्राप्य, अप्राप्य आदि हो जाता है। मामलों 'गोटो' स्पेगेटी कोड की ओर जाता है। व्यक्तिगत रूप से, मैं किसी भी अच्छे कारण के बारे में नहीं सोच सकता कि मैं 'गोटो' का उपयोग क्यों करूंगा।


11
आपके तर्क में "मैं किसी भी कारण से नहीं सोच सकता" कह रहा हूं, औपचारिक रूप से, en.wikipedia.org/wiki/Argument_from_ignorance है , हालांकि मैं शब्दावली "कल्पना की कमी से प्रमाण" पसंद करता हूं।
JUST MY सही जनमत

2
@ जस्ट माय सही ओपिनियन: अगर यह पोस्ट-हॉक कार्यरत है तो ही यह एक तार्किक गिरावट है। एक भाषा डिजाइनर के दृष्टिकोण से यह एक विशेषता ( goto)) की लागत का वजन करने के लिए एक वैध तर्क हो सकता है । @ cschol का उपयोग समान है: हालांकि अभी कोई भाषा डिज़ाइन नहीं कर रहा है, लेकिन वह मूल रूप से डिज़ाइनर के प्रयास का मूल्यांकन कर रहा है।
कोनराड रुडोल्फ

1
@KonradRudolph: IMHO, एक भाषा gotoको संदर्भों को छोड़कर अनुमति देता है जहां यह चर को अस्तित्व में लाएगा, किसी भी तरह की नियंत्रण संरचना का समर्थन करने की कोशिश करने की तुलना में सस्ता हो सकता है। gotoकुछ अन्य संरचना का उपयोग करने के साथ कोड लिखना उतना अच्छा नहीं हो सकता है, लेकिन इस तरह के कोड को goto"अभिव्यक्ति में छेद" से बचाने में मदद करेगा - ऐसे निर्माण जिनके लिए एक भाषा कुशल कोड लिखने में असमर्थ है।
सुपरकाट

1
@supercat मुझे डर है कि हम मूल रूप से भाषा डिजाइन के विभिन्न स्कूलों से हैं। मैं भाषाओं को समझने की क्षमता (या शुद्धता) की कीमत पर अधिकतम अभिव्यक्त होने पर आपत्ति करता हूं। मैं बल्कि एक अनुमेय भाषा से एक प्रतिबंधक होगा।
कोनराड रुडोल्फ

1
@ हां मैं निश्चित रूप से करता हूं। यह अक्सर पढ़ने के लिए और के बारे में कारण के लिए कोड बहुत कठिन बनाता है । वस्तुतः हर बार जब कोई कोड gotoकोड की समीक्षा साइट पर कोड gotoडालता है , तो कोड के तर्क को समाप्त कर देता है।
कोनराड रुडोल्फ

1

जीओटीओ का उपयोग किया जा सकता है, लेकिन कोड शैली की तुलना में एक और महत्वपूर्ण बात है, या यदि कोड का उपयोग करने योग्य है या नहीं, तो आपको इसका उपयोग करते समय ध्यान में रखना होगा: कोड आपके अंदर उतना मजबूत नहीं हो सकता है सोचो

उदाहरण के लिए, निम्नलिखित दो कोड स्निपेट देखें:

If A <> 0 Then A = 0 EndIf
Write("Value of A:" + A)

GOTO के साथ एक समान कोड

If A == 0 Then GOTO FINAL EndIf
   A = 0
FINAL:
Write("Value of A:" + A)

पहली चीज जो हम सोचते हैं, वह यह है कि कोड के दोनों बिट्स का परिणाम यह होगा कि "वैल्यू ऑफ ए: 0" (हम समानता के बिना किसी निष्पादन को मानते हैं, निश्चित रूप से)

यह सही नहीं है: पहले नमूने में, A हमेशा 0 होगा, लेकिन दूसरे नमूने में (GOTO स्टेटमेंट के साथ) A 0. नहीं हो सकता है? क्यों?

इसका कारण यह है कि कार्यक्रम के एक अन्य बिंदु से मैं GOTO FINALए के मूल्य को नियंत्रित किए बिना सम्मिलित कर सकता हूं ।

यह उदाहरण बहुत स्पष्ट है, लेकिन जैसे-जैसे कार्यक्रम अधिक जटिल होते हैं, उन प्रकार की चीजों को देखने की कठिनाई बढ़ जाती है।

संबंधित सामग्री श्री दिक्जस्त्र के प्रसिद्ध लेख "गो टू स्टेटमेंट के खिलाफ एक मामला" में पाया जा सकता है


6
पुराने स्कूल-बेसिक में अक्सर ऐसा होता था। आधुनिक संस्करण में, हालांकि, आपको किसी अन्य फ़ंक्शन के बीच में कूदने की अनुमति नहीं है ... या कई मामलों में, यहां तक ​​कि एक चर की घोषणा के अतीत में भी। मूल रूप से (दंडित इरादा नहीं), आधुनिक भाषाओं ने मोटे तौर पर "बेलगाम" GOTO के साथ दूर किया है, जिसके बारे में दिज्कस्ट्रा बात कर रहा था ... और इसका उपयोग करने का एकमात्र तरीका जैसा कि वह खिलाफ बहस कर रहा था, कुछ अन्य जघन्य पाप करना है। :)
cHao

1

मैं निम्नलिखित मामले में गोटो का उपयोग करता हूं: जब विभिन्न स्थानों पर फफूंदों से लौटने की आवश्यकता होती है, और लौटने से पहले कुछ अनैच्छिककरण करने की आवश्यकता होती है:

गैर-गोटो संस्करण:

int doSomething (struct my_complicated_stuff *ctx)    
{
    db_conn *conn;
    RSA *key;
    char *temp_data;
    conn = db_connect();  


    if (ctx->smth->needs_alloc) {
      temp_data=malloc(ctx->some_size);
      if (!temp_data) {
        db_disconnect(conn);
        return -1;      
        }
    }

    ...

    if (!ctx->smth->needs_to_be_processed) {
        free(temp_data);    
        db_disconnect(conn);    
        return -2;
    }

    pthread_mutex_lock(ctx->mutex);

    if (ctx->some_other_thing->error) {
        pthread_mutex_unlock(ctx->mutex);
        free(temp_data);
        db_disconnect(conn);        
        return -3;  
    }

    ...

    key=rsa_load_key(....);

    ...

    if (ctx->something_else->error) {
         rsa_free(key); 
         pthread_mutex_unlock(ctx->mutex);
         free(temp_data);
         db_disconnect(conn);       
         return -4;  
    }

    if (ctx->something_else->additional_check) {
         rsa_free(key); 
         pthread_mutex_unlock(ctx->mutex);
         free(temp_data);
         db_disconnect(conn);       
         return -5;  
    }


    pthread_mutex_unlock(ctx->mutex);
    free(temp_data);    
    db_disconnect(conn);    
    return 0;     
}

गोटो संस्करण:

int doSomething_goto (struct my_complicated_stuff *ctx)
{
    int ret=0;
    db_conn *conn;
    RSA *key;
    char *temp_data;
    conn = db_connect();  


    if (ctx->smth->needs_alloc) {
      temp_data=malloc(ctx->some_size);
      if (!temp_data) {
            ret=-1;
           goto exit_db;   
          }
    }

    ...

    if (!ctx->smth->needs_to_be_processed) {
        ret=-2;
        goto exit_freetmp;      
    }

    pthread_mutex_lock(ctx->mutex);

    if (ctx->some_other_thing->error) {
        ret=-3;
        goto exit;  
    }

    ...

    key=rsa_load_key(....);

    ...

    if (ctx->something_else->error) {
        ret=-4;
        goto exit_freekey; 
    }

    if (ctx->something_else->additional_check) {
        ret=-5;
        goto exit_freekey;  
    }

exit_freekey:
    rsa_free(key);
exit:    
    pthread_mutex_unlock(ctx->mutex);
exit_freetmp:
    free(temp_data);        
exit_db:
    db_disconnect(conn);    
    return ret;     
}

दूसरा संस्करण इसे आसान बनाता है, जब आपको डील्लोकेशन स्टेटमेंट्स में कुछ बदलने की आवश्यकता होती है (प्रत्येक कोड में एक बार उपयोग किया जाता है), और नई शाखा जोड़ते समय उनमें से किसी को भी छोड़ने का मौका कम कर देता है। एक फ़ंक्शन में उन्हें ले जाने से यहां मदद नहीं मिलेगी, क्योंकि डीललोकेशन अलग-अलग "स्तरों" पर किया जा सकता है।


3
यही कारण है कि हमारे पास finally
जॉन सॉन्डर्स

^ @JohnSaunders ने कहा। यह "गोटो का उपयोग करने का एक उदाहरण है क्योंकि एक भाषा में उपयुक्त नियंत्रण निर्माण का अभाव है"। कभी-कभी यह एक कोड गंध होता है जिसके लिए MULTIPLE गोटो अंक की आवश्यकता होती है। एक प्रोग्रामिंग शैली है जो सुरक्षित है (आसानी से खराब नहीं होती है ) और गोटो की आवश्यकता नहीं होती है, जो "अंत में" बिना भाषाओं में भी ठीक काम करता है: उन "क्लीन-अप" कॉल को डिज़ाइन करें ताकि वे साफ न होने पर हानिरहित हों। ऊपर की आवश्यकता है। फैक्टर सब कुछ लेकिन क्लीनअप ए मेथड, जो मल्टीपल-रिटर्न डिजाइन का उपयोग करता है। उस विधि को कॉल करें, फिर क्लीन-अप कॉल करें।
टूलमेकरस्टेव

ध्यान दें कि मैं जिस दृष्टिकोण का वर्णन करता हूं उसके लिए अतिरिक्त स्तर की विधि कॉल की आवश्यकता होती है (लेकिन केवल उस भाषा में जिसका अभाव है finally)। एक विकल्प के रूप में, gotoएस का उपयोग करें , लेकिन एक सामान्य निकास बिंदु पर, जो हमेशा सभी सफाई करता है । लेकिन प्रत्येक सफाई-विधि या तो एक मूल्य को संभाल सकती है जो अशक्त या पहले से ही साफ है, या सशर्त परीक्षण द्वारा संरक्षित है, इसलिए जब उचित नहीं हो तो छोड़ दिया जाता है।
टूलमेकरस्टेव

@ToolmakerSteve यह एक कोड गंध नहीं है; वास्तव में, यह C में एक अत्यंत सामान्य पैटर्न है और इसे गोटो का उपयोग करने के सबसे वैध तरीकों में से एक माना जाता है। आप चाहते हैं कि मैं 5 तरीके बनाऊं, जिनमें से प्रत्येक अपने स्वयं के अनावश्यक के साथ परीक्षण करें, बस इस फ़ंक्शन से सफाई को संभालने के लिए? आपने अब कोड और प्रदर्शन ब्लोट बनाया है। या आप सिर्फ गोटो का उपयोग कर सकते हैं।
मुसबुल्ला

@muusbolla - 1) "5 विधियाँ बनाएँ" - नहीं। मैं एक एकल विधि का सुझाव दे रहा हूँ जो ऐसे संसाधनों को साफ़ करती है जो एक गैर-शून्य मान रखते हैं। या मेरा विकल्प देखें, जो कि gotoएस का उपयोग करता है, सभी एक ही निकास बिंदु पर जाते हैं, जिसमें एक ही तर्क होता है (जिसे संसाधन के अनुसार अतिरिक्त की आवश्यकता होती है, जैसा कि आप कहते हैं)। लेकिन कोई बात नहीं, जब Cआप सही उपयोग करते हैं - कोड में जो भी कारण है, तो इसका लगभग निश्चित रूप से एक व्यापार-बंद है जो सबसे "प्रत्यक्ष" कोड का पक्षधर है। (मेरा सुझाव उन जटिल स्थितियों को संभालता है जहाँ किसी भी दिए गए संसाधन को आवंटित किया जा सकता है या नहीं किया जा सकता है। लेकिन हाँ, इस मामले में ओवरकिल करें।)
टूलमेकर

0

कंप्यूटर वैज्ञानिक, जो क्षेत्र में प्रमुख योगदान देते थे, एग्जेर डिक्जस्ट्रा भी, गोआ के उपयोग की आलोचना करने के लिए प्रसिद्ध थे। विकिपीडिया पर उनके तर्क के बारे में एक छोटा लेख है ।


0

यह समय-समय पर चरित्र-वार स्ट्रिंग प्रसंस्करण के लिए काम में आता है।

इस प्रिंटफ-एस्क उदाहरण की तरह कुछ कल्पना करें:

for cur_char, next_char in sliding_window(input_string) {
    if cur_char == '%' {
        if next_char == '%' {
            cur_char_index += 1
            goto handle_literal
        }
        # Some additional logic
        if chars_should_be_handled_literally() {
            goto handle_literal
        }
        # Handle the format
    }
    # some other control characters
    else {
      handle_literal:
        # Complicated logic here
        # Maybe it's writing to an array for some OpenGL calls later or something,
        # all while modifying a bunch of local variables declared outside the loop
    }
}

आप goto handle_literalइसे एक फ़ंक्शन कॉल के लिए रिफ्लेक्टर कर सकते हैं , लेकिन यदि यह कई अलग-अलग स्थानीय चर को संशोधित कर रहा है, तो आपको प्रत्येक के संदर्भों को पास करना होगा जब तक कि आपकी भाषा परस्पर बंद का समर्थन नहीं करती। continueयदि आपके तर्क से कोई और काम नहीं करता है तो आपको एक ही शब्दार्थ प्राप्त करने के लिए कॉल के बाद भी आपको एक स्टेटमेंट (जो कि गोटो का एक रूप है) का उपयोग करना होगा।

मैंने भी लेक्सर्स में गोटो का विवेकपूर्ण उपयोग किया है, आमतौर पर इसी तरह के मामलों के लिए। आप उन्हें ज्यादातर समय की जरूरत नहीं है, लेकिन वे उन अजीब मामलों के लिए अच्छा कर रहे हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.