जब इन स्पष्ट और प्रासंगिक मामलों के लिए इसका उपयोग किया जाता है तो गोटो के साथ क्या बुरा है?


40

मैं हमेशा से जानता हूं कि gotoकुछ बुरा है, एक तहखाने में बंद है, कभी भी अच्छे के लिए नहीं देखा जाता है, लेकिन मैं आज एक कोड उदाहरण में भाग गया जो उपयोग करने के लिए सही समझ में आता है goto

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

<?php

$ip = '192.168.1.5';
$ips = [
    '192.168.1.3',
    '192.168.1.4',
    '192.168.1.5',
];

foreach ($ips as $i) {
    if ($ip === $i) {
        goto allowed;
    }
}

throw new Exception('Not allowed');

allowed:

...

अगर मैं उपयोग नहीं करता हूं gotoतो मुझे कुछ चर का उपयोग करना होगा

$allowed = false;

foreach ($ips as $i) {
    if ($ip === $i) {
        $allowed = true;
        break;
    }
}

if (!$allowed) {
    throw new Exception('Not allowed');
}

मेरा प्रश्न यह है कि gotoजब यह इतने स्पष्ट और वास्तविक प्रासंगिक मामलों के लिए उपयोग किया जाता है तो क्या बुरा है ?


टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
maple_shaft

जवाबों:


120

GOTO अपने आप में एक तात्कालिक समस्या नहीं है, यह अंतर्निहित राज्य मशीनें हैं जिन्हें लोग इसके साथ कार्यान्वित करते हैं। आपके मामले में, आप ऐसा कोड चाहते हैं जो यह जांचे कि आईपी एड्रेस अनुमत पते की सूची में है या नहीं

if (!contains($ips, $ip)) throw new Exception('Not allowed');

इसलिए आपका कोड एक शर्त की जांच करना चाहता है। इस चेक को लागू करने के लिए एल्गोरिथ्म यहाँ कोई चिंता का विषय नहीं होना चाहिए, आपके मुख्य कार्यक्रम के मानसिक स्थान में चेक परमाणु है। इसे ऐसा होना चाहिए।

लेकिन अगर आप उस कोड को डालते हैं जो चेक को आपके मुख्य प्रोग्राम में डालता है, तो आप उसे खो देते हैं। आप पारस्परिक स्थिति का परिचय देते हैं, या तो स्पष्ट रूप से:

$list_contains_ip = undef;        # STATE: we don't know yet

foreach ($ips as $i) {
  if ($ip === $i) {
      $list_contains_ip = true;   # STATE: positive
      break;
  }
                                  # STATE: we still don't know yet, huh?                                                          
                                  # Well, then...
  $list_contains_ip = false;      # STATE: negative
}

if (!$list_contains_ip) {
  throw new Exception('Not allowed');
}

$list_contains_ipआपका एकमात्र राज्य चर कहां है, या स्पष्ट रूप से:

                             # STATE: unknown
foreach ($ips as $i) {       # What are we checking here anyway?
  if ($ip === $i) {
    goto allowed;            # STATE: positive
  }
                             # STATE: unknown
}
                             # guess this means STATE: negative
throw new Exception('Not allowed');

allowed:                     # Guess we jumped over the trap door

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

if ($ip =~ /:/) goto IP_V6;
if ($ip =~ /\//) goto IP_RANGE;
if ($ip =~ /^10\./) goto IP_IS_PRIVATE;

foreach ($ips as $i) { ... }

IP_IS_PRIVATE:
   foreach ($ip_priv as $i) { ... }

IP_V6:
   foreach ($ipv6 as $i) { ... }

IP_RANGE:
   # i don't even want to know how you'd implement that

ALLOWED:
   # Wait, is this code even correct?
   # There seems to be a bug in here.

और जिस किसी को भी उस कोड को डिबग करना है वह आपको और आपके बच्चों को शाप देगा।

दिज्क्स्त्र इसे इस तरह रखता है:

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

और इसीलिए GOTO को हानिकारक माना जाता है।


22
यह $list_contains_ip = false;कथन गलत लगता है
बर्गी २५'१६ को

1
कंकड़ से भरा एक बैग आसान है, मुझे उन्हें पकड़ने के लिए एक सुविधाजनक बैग मिला है। : पी
whatsisname

13
@ बरगी: आप सही कह रहे हैं। इससे पता चलता है कि इन चीजों को गड़बड़ाना कितना आसान है।
Wallenborn

6
@whatsisname उस बैग को फंक्शन / क्लास / पैकेज कहा जाता है। गोटो का इस्तेमाल करना उन्हें हथकंडा दिखाने और थैले को दूर फेंकने जैसा है।
फाल्को

5
मुझे दीक्जस्ट्रा के उद्धरण से प्यार है, मैंने इसे इस तरह से नहीं सुना था लेकिन यह वास्तव में एक अच्छा बिंदु है। प्रवाह के बजाय यह बहुत ऊपर से नीचे है, अचानक आपके पास कुछ ऐसा है जो यादृच्छिक पर पूरे पृष्ठ पर कूद सकता है। यह कहना कि रसीला बहुत प्रभावशाली है।
बिल के

41

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

if (!in_array($ip, $ips)) throw new Exception('Not allowed');

तो क्या इतना बुरा है GOTO? संरचित प्रोग्रामिंग कोड को व्यवस्थित करने के लिए फ़ंक्शंस और नियंत्रण संरचनाओं का उपयोग करता है इसलिए वाक्य रचना संरचना तार्किक संरचना को दर्शाती है। यदि किसी चीज को केवल सशर्त निष्पादित किया जाता है, तो यह एक सशर्त विवरण ब्लॉक में दिखाई देगा। यदि किसी लूप में कुछ निष्पादित होता है, तो यह लूप ब्लॉक में दिखाई देगा। GOTOमनमाने ढंग से चारों ओर छलांग लगाकर आप वाक्य रचना को दरकिनार करने में सक्षम हो जाते हैं, जिससे कोड का पालन करना बहुत कठिन हो जाता है।

बेशक, अगर आपके पास कोई अन्य विकल्प नहीं है GOTO, लेकिन यदि आप उसी प्रभाव को कार्यों और नियंत्रण संरचनाओं के साथ प्राप्त कर सकते हैं, तो यह बेहतर है।


5
@jameslarge it's easier to write good optimizing compilers for "structured" languages.विस्तृत करने के लिए देखभाल? एक काउंटर उदाहरण के रूप में, रस्ट लोगों ने एमआईआर पेश किया, संकलक में एक मध्यवर्ती प्रतिनिधित्व जो विशेष रूप से लूप को बदलता है, जारी रखता है, टूटता है, और गोटो के साथ ऐसा होता है, क्योंकि यह जांचना और अनुकूलन करना अधिक सरल है।
8bittree

6
"यदि आपके पास कोई दूसरा विकल्प नहीं है तो आप GOTO का उपयोग करें" यह अत्यधिक दुर्लभ होगा। मैं ईमानदारी से एक ऐसे मामले के बारे में नहीं सोच सकता, जहां आपके पास कोई दूसरा विकल्प नहीं है, मौजूदा कोड या समान बकवास को रोकने के लिए पूरी तरह से अजीब प्रतिबंधों के बाहर ।
jpmc26

8
इसके अलावा, IMO, gotoझंडे और सशर्त के चूहों के घोंसले के साथ अनुकरण (ओपी के दूसरे उदाहरण के रूप में) एक का उपयोग करके जूट की तुलना में बहुत कम पठनीय है goto

3
@ 8bittree: संरचित प्रोग्रामिंग स्रोत भाषा के लिए है, संकलक की लक्षित भाषा नहीं। देशी compilers के लिए लक्षित भाषा सीपीयू निर्देश है, जो निश्चित रूप से है नहीं "संरचित," प्रोग्रामिंग भाषा के अर्थ में।
रॉबर्ट हार्वे

4
@ 8bittree MIR के बारे में आपके प्रश्न का उत्तर आपके द्वारा दिए गए लिंक में है: "लेकिन MIR में ऐसा निर्माण होना ठीक है, क्योंकि हम जानते हैं कि इसका उपयोग केवल विशेष तरीकों से किया जाएगा, जैसे कि लूप या ब्रेक को व्यक्त करना । " दूसरे शब्दों में, क्योंकि गस्टो को रस्ट में अनुमति नहीं है, वे जानते हैं कि यह संरचित है और गोटो के साथ मध्यवर्ती संस्करण भी है। अंतत: कोड को मशीन कमांड की तरह गोटो में उतरना पड़ता है। आपके लिंक से मुझे जो मिल रहा है वह यह है कि वे उच्च-स्तर से निम्न-स्तरीय भाषा में रूपांतरण में एक वृद्धिशील कदम जोड़ रहे हैं।
जिम्मीजम्स २०

17

जैसा कि दूसरों ने कहा है, समस्या gotoस्वयं के साथ नहीं है; समस्या यह है कि लोग कैसे उपयोग करते हैं goto, और यह कैसे कोड को समझने और बनाए रखने के लिए कठिन बना सकता है।

निम्नलिखित स्निपेट को कोड मानें:

       i = 4;
label: printf( "%d\n", i );

किस मूल्य के लिए मुद्रित किया जाता है i? यह कब छपता है? जब तक आप अपने समारोह में हर उदाहरण के लिए खाते हैं goto label, आप नहीं जान सकते। उस लेबल की सरल उपस्थिति सरल निरीक्षण द्वारा कोड डिबग करने की आपकी क्षमता को नष्ट कर देती है । एक या दो शाखाओं के साथ छोटे कार्यों के लिए, बहुत अधिक समस्या नहीं है। छोटे कार्यों के लिए नहीं ...

90 के दशक की शुरुआत में हमें C कोड का ढेर दिया गया, जिसने एक 3 डी ग्राफिकल डिस्प्ले को प्रदर्शित किया और इसे तेजी से चलाने के लिए कहा। यह कोड की केवल 5000 पंक्तियों के बारे में था, लेकिन यह सभी में था main, और लेखक ने gotoदोनों दिशाओं में लगभग 15 या तो एस शाखा का उपयोग किया था । यह शुरू करने के लिए बुरा कोड था , लेकिन उन लोगों की उपस्थिति gotoने इसे इतना बदतर बना दिया। नियंत्रण के प्रवाह को समझने में मेरे सहकर्मी को लगभग 2 सप्ताह का समय लगा। इससे भी बेहतर, उन gotoकोडों के परिणामस्वरूप इतनी मजबूती से खुद को जोड़ लिया गया कि हम बिना कुछ तोड़े बदलाव नहीं कर सकते थे

हमने स्तर 1 अनुकूलन के साथ संकलन करने की कोशिश की, और संकलक ने सभी उपलब्ध रैम को खा लिया, फिर सभी उपलब्ध स्वैप किया, और फिर सिस्टम को घबरा दिया (जिसका शायद खुद से कोई लेना-देना नहीं था goto, लेकिन मुझे उस उपाख्यान को वहां फेंकना पसंद है)।

अंत में, हमने ग्राहक को दो विकल्प दिए - आइए हम पूरी बात को स्क्रैच से फिर से लिखें, या तेजी से हार्डवेयर खरीदें।

उन्होंने तेजी से हार्डवेयर खरीदे।

उपयोग करने के लिए बोड के नियम goto:

  1. शाखा ही आगे;
  2. नियंत्रण संरचनाओं को बायपास न करें (यानी, ifया forया whileबयान के शरीर में शाखा न करें );
  3. gotoएक नियंत्रण संरचना के स्थान पर उपयोग न करें

वहाँ मामलों में जहां एक कर रहे हैं goto है सही जवाब है, लेकिन वे दुर्लभ हैं (एक गहरा नेस्टेड लूप से बाहर तोड़ने के बारे में केवल जगह मैं इसका इस्तेमाल होता है)।

संपादित करें

उस अंतिम विवरण पर विस्तार करते हुए, यहाँ के लिए कुछ मान्य उपयोग मामलों में से एक है goto। मान लें कि हमारे पास निम्नलिखित कार्य हैं:

T ***myalloc( size_t N, size_t M, size_t P )
{
  size_t i, j, k;

  T ***arr = malloc( sizeof *arr * N );
  for ( i = 0; i < N; i ++ )
  {
    arr[i] = malloc( sizeof *arr[i] * M );
    for ( j = 0; j < M; j++ )
    {
      arr[i][j] = malloc( sizeof *arr[i][j] * P );
      for ( k = 0; k < P; k++ )
        arr[i][j][k] = initial_value();
    }
  }
  return arr;
}

अब, हमारे पास एक समस्या है - क्या होगा यदि mallocकॉल में से एक के बीच में विफल रहता है? पूरी तरह से एक घटना है कि हो सकता है, हम एक आंशिक रूप से आवंटित सरणी वापस नहीं करना चाहते हैं, और न ही हम केवल एक त्रुटि के साथ समारोह से बाहर जमानत चाहते हैं; हम अपने आप को साफ करना चाहते हैं और किसी भी आंशिक रूप से आवंटित मेमोरी को हटा देना चाहते हैं। एक भाषा में जो एक खराब आवंटन पर एक अपवाद फेंकता है, वह काफी सीधा है - आप सिर्फ एक अपवाद हैंडलर को खाली करने के लिए लिखते हैं जो पहले से ही आवंटित किया गया है।

C में, आपके पास संरचित अपवाद हैंडलिंग नहीं है; आपको प्रत्येक mallocकॉल के रिटर्न मूल्य की जांच करनी होगी और उचित कार्रवाई करनी होगी ।

T ***myalloc( size_t N, size_t M, size_t P )
{
  size_t i, j, k;

  T ***arr = malloc( sizeof *arr * N );
  if ( arr )
  {
    for ( i = 0; i < N; i ++ )
    {
      if ( !(arr[i] = malloc( sizeof *arr[i] * M )) )
        goto cleanup_1;

      for ( j = 0; j < M; j++ )
      {
        if ( !(arr[i][j] = malloc( sizeof *arr[i][j] * P )) )
          goto cleanup_2;

        for ( k = 0; k < P; k++ )
          arr[i][j][k] = initial_value();
      }
    }
  }
  goto done;

  cleanup_2:
    // We failed while allocating arr[i][j]; clean up the previously allocated arr[i][j]
    while ( j-- )
      free( arr[i][j] );
    free( arr[i] );
    // fall through

  cleanup_1:
    // We failed while allocating arr[i]; free up all previously allocated arr[i][j]
    while ( i-- )
    {
      for ( j = 0; j < M; j++ )
        free( arr[i][j] );
      free( arr[i] );
    }

    free( arr );
    arr = NULL;

  done:
    return arr;
}

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


मुझे ये नियम पसंद हैं। मैं अभी भी प्रयोग नहीं करेंगे gotoयहां तक कि इन के अनुसार नियम-मैं पर इसका इस्तेमाल नहीं होता सब जब तक यह उपलब्ध शाखाओं का ही रूप है भाषा-लेकिन मैं देख सकता हूँ कि यह बहुत ज्यादा डिबग करने के लिए एक बुरा सपना का नहीं होगा gotoयदि वे इन नियमों के अनुसार लिखे गए थे।
वाइल्डकार्ड

यदि आपको एक गहरी नेस्टेड लूप से बाहर निकलने की आवश्यकता है, तो आपको बस उस लूप को एक और कार्य करने की जरूरत है और वापसी
bunyaCloven

6
जैसा कि किसी ने एक बार मेरे लिए संक्षेप में कहा था: "यह एक समस्या नहीं है, यह एक समस्या है"। एक सॉफ्टवेयर ऑप्टिमाइज़ेशन विशेषज्ञ के रूप में, मैं मानता हूं कि असंरचित नियंत्रण प्रवाह एक लूप के लिए संकलक (और मानव!) फेंक सकता है। मैंने एक बार बीएलएएस फ़ंक्शन में एक साधारण राज्य मशीन (चार राज्यों में से चार) को GOTOडिक्रिप्ट करने में घंटों का समय बिताया, जिसमें फ़ोर्ट्रन (में) प्रसिद्ध सौंपा और अंकगणितीय गोटो सहित विभिन्न रूपों का उपयोग किया गया था, अगर मैं सही ढंग से याद करता हूं।
njuffa

@njuffa "एक सॉफ्टवेयर ऑप्टिमाइज़ेशन विशेषज्ञ के रूप में मैं यह सुनिश्चित करता हूं कि असंरचित नियंत्रण प्रवाह लूप के लिए संकलक (और बच्चे) को फेंक सकता है।" - किसी भी अधिक जानकारी? मैंने सोचा था कि आजकल हर अनुकूलन करने वाला कंपाइलर SSA का उपयोग IR के रूप में करता है, जिसका अर्थ है कि यह गोटो-जैसे कोड का उपयोग कर रहा है।
मैकीज पीचोटका

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

12

return, break, continueऔर throw/ catchएक और कोड करने के लिए सभी हस्तांतरण नियंत्रण वे और सभी gotos साथ लागू किया जा सकता है - - सभी अनिवार्य रूप से gotos हैं वास्तव में मैं एक स्कूल परियोजना में तो एक बार किया था, एक पास्कल प्रशिक्षक कह रहे थे कितना बेहतर पास्कल से था बुनियादी संरचना के कारण ... इसलिए मुझे इसके विपरीत होना पड़ा ...

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

वर्षों से भाषाओं में जो सुविधाएँ जोड़ी गई हैं उनमें से अधिकांश सॉफ़्टवेयर को अधिक बनाए रखने के लिए हैं, लिखना आसान नहीं है (हालाँकि कुछ भाषाएँ उस दिशा में जाती हैं - वे अक्सर दीर्घकालिक समस्याओं का कारण बनती हैं ...)।

समान प्रवाह नियंत्रण कथनों की तुलना में, GOTO अपने सबसे अच्छे रूप में अनुसरण करने में आसान हो सकते हैं (आपके द्वारा सुझाए गए मामले में उपयोग किया जाने वाला एक एकल गोटो), और एक दुःस्वप्न जब दुर्व्यवहार किया जाता है - और बहुत आसानी से दुरुपयोग किया जाता है ...

इसलिए कुछ वर्षों के लिए स्पेगेटी बुरे सपने से निपटने के बाद हमने सिर्फ "नहीं" कहा, एक समुदाय के रूप में हम इसे स्वीकार नहीं करने जा रहे हैं - बहुत सारे लोग इसे गड़बड़ कर देते हैं अगर थोड़ा सा रास्ता दिया जाता है - तो यह वास्तव में उनके साथ एकमात्र समस्या है। आप उनका उपयोग कर सकते हैं ... लेकिन भले ही यह बिल्कुल सही मामला है, अगले आदमी को आप एक भयानक प्रोग्रामर मानेंगे क्योंकि आप समुदाय के इतिहास को नहीं समझते हैं।

आपके कोड को और अधिक समझने के लिए कई अन्य संरचनाओं को विकसित किया गया है: फ़ंक्शंस, ऑब्जेक्ट्स, स्कोपिंग, एन्कैप्स, कमेंट्स (!) ... साथ ही साथ "DRY" (नकल रोकने) और "YAGNI" जैसे अधिक महत्वपूर्ण पैटर्न / प्रक्रियाएं! (कोड के अति-सामान्यीकरण / जटिलता को कम करना) - सभी वास्तव में केवल आपके कोड को पढ़ने के लिए अगले व्यक्ति के लिए आयात करते हैं (जो शायद आप होंगे - आपके द्वारा पहली बार में किए गए अधिकांश कार्यों को भूल जाने के बाद!)


3
मैं इसे केवल वाक्य के लिए बढ़ा रहा हूं, "सबसे महत्वपूर्ण बात ... कोड को पठनीय बनाना है; कुछ करने के लिए प्राप्त करना लगभग माध्यमिक है।" मैं इसे थोड़े अलग ढंग से कहूंगा; यह इतना सरल कोड बनाने के रूप में पठनीय कोड नहीं है । लेकिन किसी भी तरह, यह ओह-तो-सच है कि यह कर रही है ऐसा कुछ गौण है।
वाइल्डकार्ड

" return, break, continueऔर throw/ catchसभी अनिवार्य रूप से gotos" असहमत हैं, पूर्व सम्मान के सिद्धांतों संरचित प्रोग्रामिंग (आप अपवाद के बारे में बहस कर सकते हैं, हालांकि), जाना करने के लिए निश्चित रूप से नहीं करता है। इस प्रश्न के प्रकाश में, इस टिप्पणी से बहुत कुछ हासिल नहीं हुआ है।
एरिक

@eric आप GOTOs के साथ किसी भी कथन को मॉडल कर सकते हैं। आप यह सुनिश्चित कर सकते हैं कि GOTO सभी संरचित प्रोग्रामिंग टेनसेट्स से सहमत हैं - उनके पास बस एक अलग सिंटैक्स और होना चाहिए, ताकि कार्यक्षमता को वास्तव में डुप्लिकेट करने के लिए, "if" जैसे अन्य ऑपरेशन शामिल हों। संरचित संस्करणों का लाभ यह है कि वे केवल कुछ लक्ष्यों का समर्थन करने के लिए ही सीमित हैं - आप जानते हैं कि जब आप लगभग एक लक्ष्य देखते हैं, जहां लक्ष्य स्थित होगा। जिस कारण से मैंने इसका उल्लेख किया वह यह था कि यह अपमानजनक है कि यह समस्या है, यह नहीं कि इसका सही उपयोग नहीं किया जा सकता है।
बिल के

7

GOTOएक उपकरण है। इसका उपयोग अच्छे या बुरे के लिए किया जा सकता है।

बुरे पुराने दिनों में, फोरट्रान और बेसिक के साथ, यह लगभग एकमात्र उपकरण था।

उन दिनों के कोड को देखते समय, जब आप देखते हैं कि GOTOआपको यह पता लगाना है कि यह क्यों है। यह एक मानक मुहावरे का हिस्सा हो सकता है जिसे आप जल्दी समझ सकते हैं ... या यह कुछ बुरे नियंत्रण संरचना का हिस्सा हो सकता है जो कभी नहीं होना चाहिए। आपको तब तक नहीं पता है जब तक आपने देखा नहीं है, और गलत होना आसान है।

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

विडंबना GOTOयह है कि यह बहुत कम नहीं है जब यह दुर्लभ हो। जब आप एक को देखते हैं, तो आप जानते हैं कि कुछ विशेष चल रहा है, और संबंधित लेबल को ढूंढना आसान है क्योंकि यह पास का एकमात्र लेबल है।

आज तेजी से आगे। आप प्रोग्रामिंग सिखाने वाले लेक्चरर हैं। आप कह सकते हैं "ज्यादातर मामलों में आपको उन्नत नए निर्माणों का उपयोग करना चाहिए, लेकिन कुछ मामलों में एक सरल GOTOअधिक पठनीय हो सकता है।" छात्रों को यह समझ में नहीं आ रहा है। वे GOTOअपठनीय कोड बनाने के लिए दुरुपयोग करने जा रहे हैं ।

इसके बजाय आप कहते हैं " GOTOबुरा। GOTOबुराई। GOTOपरीक्षा में असफल।" छात्र समझ जाएगा कि !


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

4

के अपवाद के साथ goto, PHP (और अधिकांश भाषाओं) में सभी प्रवाह निर्माणों को पदानुक्रम से स्कैन किया जाता है।

स्क्विट आंखों के माध्यम से जांचे गए कुछ कोड की कल्पना करें:

a;
foo {
    b;
}
c;

क्या नियंत्रण निर्माण के बावजूद fooहै ( if, while, आदि), वहाँ केवल के लिए कुछ खास अनुमति आदेश हैं a, b, और c

आप हो सकता है a- b- c, या a- cया, या a- b- b- b- c। लेकिन तुम सकता है कभी नहीं है b- cया a- b- a- c

... जब तक आपके पास नहीं है goto

$a = 1;
first:
echo 'a';
if ($a === 1) {
    echo 'b';
    $a = 2;
    goto first;
}
echo 'c'; 

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

gotoएस में एक जगह है, लेकिन ज्यादातर निम्न-स्तरीय भाषाओं में सूक्ष्म-अनुकूलन के रूप में। IMO, PHP में इसके लिए कोई अच्छी जगह नहीं है।


FYI करें, उदाहरण कोड को आपके किसी भी सुझाव से बेहतर लिखा जा सकता है।

if(!in_array($ip, $ips, true)) {
    throw new Exception('Not allowed');
}

2

निम्न स्तर की भाषाओं में GOTO अपरिहार्य है। लेकिन उच्च स्तर में इसे टाला जाना चाहिए (मामले में भाषा इसका समर्थन करती है) क्योंकि यह कार्यक्रमों को पढ़ने के लिए और अधिक कठिन बना देता है

सब कुछ कोड को पढ़ने के लिए और अधिक कठिन बनाने के लिए उबलता है। उच्च स्तर की भाषाएं supossedt o हैं जो निम्न स्तर की भाषाओं की तुलना में कोड को पढ़ना आसान बनाती हैं, जैसे, कोडांतरक या C।

GOTO ग्लोबल वार्मिंग का कारण नहीं है और न ही यह तीसरी दुनिया में गरीबी का कारण बनता है। यह सिर्फ कोड को पढ़ना अधिक कठिन बनाता है।

अधिकांश आधुनिक भाषाओं में नियंत्रण संरचनाएं हैं जो गोटो को अनावश्यक बनाती हैं। जावा की तरह कुछ भी नहीं है।

वास्तव में, शब्द स्पेगेटी कोड जटिल से आता है, असंरचित शाखाओं वाली संरचनाओं द्वारा कोड कारणों का पालन करना मुश्किल है।


6
gotoपढ़ने के लिए कोड eaiser बना सकते हैं। जब आपने अतिरिक्त चर और नेस्टेड शाखाएं बनाईं, तो एक ही छलांग के लिए कोड को पढ़ना और समझना अधिक कठिन है।
मैथ्यू Whited

@MatthewWhited शायद अगर आपके पास दस लाइन विधि में एकल गोटो है। लेकिन अधिकांश विधियाँ दस रेखाएँ लंबी नहीं होती हैं और अधिकांश बार जब लोग GOTO का उपयोग करते हैं तो वे इसका उपयोग "बस एक बार" नहीं करते हैं।
ट्यूलेंस कोर्डोवा

2
@MatthewWhited वास्तव में, शब्द स्पेगेटी कोड जटिल से आता है, असंरचित शाखाओं वाली संरचनाओं के कारण कोड का पालन करना मुश्किल है। या स्पेगेटी कोड अब लाल करना आसान है? शायद। Vinyl वापस आ रहा है, क्यों GOTO नहीं होगा।
ट्यूलेंस कोर्डोवा

3
@ मुझे विश्वास करना होगा कि ऐसी बुरी चीजें मौजूद हैं क्योंकि लोग तब तक शिकायत करते रहते हैं, लेकिन ज्यादातर बार जो मैं देखता gotoहूं, वह जटिल स्पेगेटी कोड के उदाहरण नहीं हैं, बल्कि काफी सीधी-सादी चीजों के बजाय अक्सर भाषा में नियंत्रण के प्रवाह का अनुकरण करते हैं जो डॉन इसके लिए वाक्यविन्यास नहीं है: दो सबसे आम उदाहरण हैं कई छोरों को तोड़ना और ओपी में उदाहरण जहां gotoलागू करने के लिए उपयोग किया जाता है for- else

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

1

gotoखुद बयानों में कुछ भी गलत नहीं है । गलत लोग कुछ लोगों के साथ हैं जो अनुचित रूप से बयान का उपयोग करते हैं।

जैक्सबी ने जो कहा (सी में त्रुटि से निपटने) के अलावा, आप gotoएक गैर-नेस्टेड लूप से बाहर निकलने के लिए उपयोग कर रहे हैं , कुछ ऐसा जो आप उपयोग करके कर सकते हैं break। इस मामले में आप बेहतर उपयोग करते हैं break

लेकिन अगर आपके पास एक नेस्टेड लूप परिदृश्य था, तो उपयोग gotoकरना अधिक सुरुचिपूर्ण / सरल होगा। उदाहरण के लिए:

$allowed = false;

foreach ($ips as $i) {
    foreach ($ips2 as $i2) {
        if ($ip === $i && $ip === $i2) {
            $allowed = true;
            goto out;
        }
    }
}

out:

if (!$allowed) {
    throw new Exception('Not allowed');
}

ऊपर दिए गए उदाहरण से आपकी विशिष्ट समस्या का कोई मतलब नहीं है, क्योंकि आपको नेस्टेड लूप की आवश्यकता नहीं है। लेकिन मुझे आशा है कि आप केवल नेस्टेड लूप का हिस्सा देखते हैं।

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


6
मुझे PHP के बारे में निश्चित नहीं है, लेकिन कई भाषाएं एक नंबर का उपयोग करके breakऔर continue(लूप की कई परतों को तोड़ने / जारी रखने के लिए) या एक लेबल (उस लेबल के साथ लूप को तोड़ने / जारी रखने के लिए) का समर्थन करेंगी , जिनमें से कोई भी आम तौर पर होना चाहिए gotoनेस्टेड छोरों के लिए उपयोग करने के लिए बेहतर ।
8bittree

@ 8 बिट्टी अच्छी बात है। मुझे नहीं पता था कि PHP का विराम यह कल्पना है। मुझे केवल इतना पता है कि C का ब्रेक फैंस को नहीं है। पर्ल का ब्रेक (वे इसे अंतिम कहते हैं ) भी सी के समान होता था (यानी पीएचपी के रूप में फैंसी नहीं) लेकिन यह कुछ बिंदु के बाद फैंसी बन गया। मुझे लगता है कि मेरा उत्तर कम और कम उपयोगी हो रहा है क्योंकि अधिक भाषाएं ब्रेक के फैंसी संस्करणों को पेश कर रही हैं :)
गुफाओंवाला

3
अतिरिक्त मान के बिना गहराई मान के साथ विराम समस्या का समाधान नहीं करेगा। अपने आप में एक चर जो जटिलता का एक अतिरिक्त स्तर बनाता है।
मैथ्यू Whited

बेशक, सिर्फ इसलिए कि आपके पास नेस्टेड लूप हैं इसका मतलब यह नहीं है कि आपको एक गोटो की आवश्यकता है, उस स्थिति को सुरुचिपूर्ण ढंग से संभालने के अन्य तरीके हैं।
NPSF3000 0

@ NPSF3000 क्या आप नेस्टेड लूप का एक उदाहरण पेश कर सकते हैं जिसे आप बिना गोटो स्टेटमेंट का उपयोग किए बिना बाहर निकल सकते हैं , जबकि एक ऐसी भाषा का उपयोग भी करते हैं जिसमें ब्रेक का फैंसी संस्करण नहीं है जो गहराई को निर्दिष्ट करता है?
गुफ़ा 20

0

गोटो के साथ मैं तेज कोड लिख सकता हूं!

सच। परवाह मत करो।

गोटो विधानसभा में मौजूद है! वे सिर्फ इसे जेएमपी कहते हैं।

सच। परवाह मत करो।

गोटो समस्याओं को और अधिक सरलता से हल करता है।

सच। परवाह मत करो।

एक अनुशासित डेवलपर कोड के हाथ में, जो गोटो का उपयोग करता है, पढ़ने में आसान हो सकता है।

सच। हालाँकि, मैं अनुशासित कोडर रहा हूँ। मैंने देखा है कि समय के साथ क्या होता है। Gotoठीक शुरू होता है। फिर कोड के पुन: उपयोग के लिए आग्रह करता हूं। बहुत जल्द मैं खुद को एक ब्रेकपॉइंट पर पाता हूं, जिसमें कोई लानत सुराग नहीं है कि कार्यक्रम की स्थिति को देखते हुए भी क्या हो रहा है। Gotoकोड के बारे में तर्क करना कठिन बनाता है। हम काम किया है वास्तव में कड़ी मेहनत बनाने while, do while, for, for each switch, subroutines, functionsसभी, और अधिक, क्योंकि के साथ इस काम करना ifऔर gotoमस्तिष्क पर कठिन है।

तो नहीं। हम देखना नहीं चाहते हैं goto। यकीन है कि यह जीवित और अच्छी तरह से बाइनरी में है, लेकिन हमें उस स्रोत को देखने की आवश्यकता नहीं है। वास्तव में, ifथोड़ा अस्थिर दिखना शुरू हो रहा है।


1
"गोटो समस्याओं को अधिक सरलता से हल करता है।" / "सच। परवाह नहीं है।" - मुझे आपके कोड को देखने से घृणा होगी जहां आप जानबूझकर सरल समाधानों से बचते हैं जो सबसे अधिक है। (YAGNI के बारे में सुना?)
user253751

1
@Wildcard अगर और गोटो समस्याओं को हल करने के लिए बहुत सरल तरीके हैं सबसे अच्छा अन्य तरीकों से हल किया। वे कम लटके फल हैं। यह विशेष भाषा के बारे में नहीं है। Gotoआपको कोड की समस्या को कुछ और समस्या बनाकर अमूर्त करने देता है। Ifआपको वह अमूर्तता चुनने देता है। अमूर्त के बेहतर तरीके और अमूर्त को चुनने के बेहतर तरीके हैं। एक के लिए बहुरूपता
कैंडिड_ओरेंज

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

1
@artelius "सच, परवाह नहीं" विषय का अर्थ समझाने का नहीं है। यह कई बिंदुओं को चित्रित करने के लिए है, जिन्हें मैं गोटो को स्वीकार करूंगा और अभी भी इसके खिलाफ उतरूंगा। इस प्रकार मेरे साथ उन बिंदुओं पर बहस करना व्यर्थ है। चूंकि यह मेरी बात नहीं है। मुद्दा समझो?
कैंडिड_ओरेंज

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

-1

असेंबली भाषाओं में आमतौर पर केवल सशर्त / बिना शर्त कूद (GOTO के समतुल्य होते हैं। FORTRAN और BASIC के पुराने कार्यान्वयन में कोई गणना खंड (DO DO लूप) से परे कोई नियंत्रण ब्लॉक विवरण नहीं था, जो अन्य सभी नियंत्रण प्रवाह IFs और GOTO को छोड़ देता है। DO लूप इन भाषाओं को एक संख्यात्मक रूप से लेबल किए गए बयान द्वारा समाप्त किया गया था। परिणामस्वरूप, इन भाषाओं के लिए लिखा गया कोड हो सकता है, और अक्सर था, का पालन करना कठिन और गलतियों के लिए प्रवण।

इस बिंदु को रेखांकित करने के लिए, " COME FROM " कथन का स्पष्ट रूप से आविष्कार किया गया है ।

C, C ++, C #, PASCAL, Java, आदि भाषाओं में GOTO का उपयोग करने की व्यावहारिक रूप से कोई आवश्यकता नहीं है; वैकल्पिक निर्माणों का उपयोग किया जा सकता है जो लगभग निश्चित रूप से कुशल और कहीं अधिक बनाए रखने योग्य होगा। यह सच है कि स्रोत फ़ाइल में एक GOTO कोई समस्या नहीं होगी। समस्या यह है कि इसे बनाए रखने के लिए कोड की एक इकाई का पालन करना मुश्किल है और त्रुटि-प्रवण है। इसीलिए स्वीकृत ज्ञान है कि जब भी संभव हो GOTO से बचना चाहिए।

गोटो बयान पर यह विकिपीडिया लेख उपयोगी हो सकता है

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