goto avskräcks nästan allmänt. Används detta uttalande någonsin?

Kommentarer

  • xkcd.com/292
  • goto är vad cpu i slutändan gör, men det fungerar inte bra med vad människor behöver förstå och abstrakta eftersom det inte finns något märke på målet slutet. Jämför med Intercal COMEFROM.
  • @Thorbj ø rnRavnAndersen, vad mer människor menar när de ’ talar du om tillståndsövergångar i en tillståndsmaskin? Kan ’ t du se en likhet? ” Gå till ett givet tillstånd ”, att ’ s vad det betyder och allt annat skulle bara vara en onödig komplikation av en sådan trivial sak. Och vad menar du med ” inget märke ”? Etiketten är ett sådant märke.
  • @ SK-logik, beror på hur långt borta du tillåter att ’ kommer ifrån. Statliga maskiner behöver inte gå till implementering.
  • @Thorbj ø rnRavnAndersen, naturligtvis krävs inte goto. Det är bara det mest rationella sättet att implementera dem på de tvingande språken, eftersom det är närmast själva semantiken i statsövergången. Och dess destination kan vara ganska långt från källan, den kommer inte att ’ t hindra läsbarheten. Mitt favoritexempel på en sådan kod är D.E. Knuth ’ s implementering av äventyrsspelet.

Svar

Detta har diskuterats flera gånger på Stack Overflow, och Chris Gillum sammanfattade de möjliga användningarna av goto :

Avslutar en funktion

Ofta kan du i en funktion fördela resurser och behöva lämna på flera platser. Programmerare kan förenkla sin kod genom att sätta resursrensningskoden i slutet av funktionen alla alla ” utgångspunkter ” av funktionen skulle gå rengöringsetiketten. På så sätt behöver du inte skriva upprensningskod vid varje ” utgångspunkt ” i funktionen.

Avsluta kapslade slingor

Om du är i en kapslad slinga och behöver bryta ur alla slingor, en goto kan göra detta mycket renare och enklare än bryta uttalanden och if-checks.

Prestandaförbättringar på låg nivå

Detta gäller bara i perf-kritisk kod, men goto-uttalanden körs mycket snabbt och kan ge dig en boost när du går igenom en funktion. Detta är dock ett tveeggat svärd, eftersom en kompilator vanligtvis inte kan optimera kod som innehåller foton.

Jag skulle argumentera, som många andra skulle hävda , att i alla dessa fall används användningen av goto som ett medel för att komma ut ur ett hörn man kodade sig in i, och är i allmänhet ett symptom på kod som kan omformas .

Kommentarer

  • Det första problemet löses mycket snyggt med finally block i moderna språk, och den andra löses med märkt break s. Om du ’ sitter fast med C dock goto är i stort sett det enda sättet att lösa dessa problem på ett elegant sätt.
  • Mycket bra poäng. Jag gillar hur Java tillåter att bryta ur flera nivåer av slingor
  • @Chinmay – äntligen bara blockerar gäller för 1) moderna språk som har dem och b) du kan tolerera omkostnaderna (undantagshantering har en overhead. ) Det vill säga att användning av finally endast är giltigt under dessa förhållanden. Det finns väldigt sällsynta, men ändå giltiga situationer där en goto är vägen att gå.
  • Okej människor … vad är det för skillnad mellan break 3 eller break myLabel och goto myLabel. Åh det ’ är precis nyckelordet. Om du använder break, continue eller något liknande nyckelord är du infekterad med en goto (Om du använder for, while, foreach, do/loop använder du en villkorlig goto.)
  • Om prestanda på låg nivå – den moderna processorns beteende kan vara svårt att förutsäga (pipeline, körning utan ordning) så i 99% av fallen är det förmodligen inte värt det eller till och med kan det vara långsammare. @MatthewWhited: Scoping. Om du anger omfattning vid godtycklig punkt är det inte klart (för mänskligt) vad konstruktörer ska kallas (problemet finns också i C).

Svar

Kontrollflödeskonstruktioner på högre nivå tenderar att motsvara begrepp i problemdomänen. Ett if / else är ett beslut baserat på något villkor. En slinga säger att utföra vissa åtgärder upprepade gånger. Till och med ett avbrott uttalande säger ”vi gjorde detta upprepade gånger, men nu måste vi sluta”.

Ett goto-uttalande å andra sidan tenderar att motsvara ett koncept i det pågående programmet, inte i problemdomän. Det står att fortsätta körningen vid en viss punkt i programmet . Någon som läser koden måste dra slutsatsen vad det betyder med avseende på problemdomänen.

Naturligtvis kan alla högre nivåskonstruktioner definieras i termer av foton och enkla villkorliga grenar . Det betyder inte att de bara är i förklädnad. Tänk på dem som begränsade foton – och det är begränsningarna som gör dem användbara. Ett pausmeddelande implementeras som ett hopp till slutet av den omslutande slingan, men det är bättre tänkt som fungerar på slingan som helhet.

Allt annat lika, kod vars struktur återspeglar den för problemdomänen tenderar att vara lättare att läsa och underhålla.

Det finns inga fall där ett goto-uttalande krävs absolut (det finns ”s en teorem , men det finns fall där det kan vara den minst dåliga lösningen. Dessa fall varierar från språk till språk, beroende på vilka högre nivåer som språket stöder.

I C, till exempel, tror jag att det finns tre grundläggande scenarier där en goto är lämplig.

  1. Bryter ut från en kapslad slinga. Detta skulle vara onödigt om språket hade ett märkt brytuttalande.
  2. Räddning av en kodsträcka (vanligtvis en funktionsdel) i händelse av ett fel eller annan oväntad händelse . Detta skulle vara onödigt om språket hade undantag.
  3. Implementering av en uttrycklig ändlig tillståndsmaskin. I det här fallet (och jag tror bara i det här fallet) motsvarar en goto direkt ett koncept i problemdomänen, övergår från ett tillstånd till ett specificerat annat tillstånd, där det aktuella tillståndet representeras av vilket kodblock som för närvarande körs .

Å andra sidan kan en explicit finite state-maskin också implementeras med en switch-sats i en slinga. Detta har fördelen att varje tillstånd börjar på samma plats i koden, vilket till exempel kan vara användbart för felsökning.

Huvudanvändningen av en goto på ett rimligt modernt språk (en som stöder om / else and loops) är att simulera en kontrollflödeskonstruktion som saknas i språket.

Kommentarer

  • Detta är faktiskt det bästa svaret hittills – ganska överraskande, för en fråga som är ett och ett halvt år gammal. 🙂
  • +1 till ” bästa svaret hittills ”. — ” Huvudanvändningen av en goto på ett rimligt modernt språk (en som stöder if / else och loopar) är att simulera ett kontrollflöde konstruera att ’ saknas från språket. ”
  • I switch-statement state machine, varje skriv till kontrollvärdet är verkligen en goto. SSSM ’ s är ofta bra strukturer att använda, eftersom de ser parera ut SM-tillståndet från exekveringskonstruktionen, men de eliminerar inte ’ t ” gotos ”.
  • ” Allt annat är lika, kod vars struktur återspeglar problemdomänens tendens att vara lättare att läsa och underhålla. div id = ”877889c4e5”>

Jag ’ har vetat detta helt länge men saknade orden för att så exakt kommunicera det på ett sätt som andra programmerare kan och kommer faktiskt att förstå. Tack för detta.

  • ” strukturerad programsats ” roar mig, eftersom det tenderar att tydligt visa poäng att använda strukturerade programmeringsuttalanden för att emulera en goto är mycket mindre läsbar än att bara använda en goto!
  • Svar

    Visst beror det på programmeringsspråket. Den främsta anledningen till att goto har varit kontroversiell är på grund av dess dåliga effekter som uppstår när kompilatorn låter dig använda den för liberalt. Problem kan uppstå, till exempel om det låter dig använda goto på ett sådant sätt att du nu kan komma åt en oinitialiserad variabel, eller värre, för att hoppa in i en annan metod och röra med samtalet stack. Det borde vara kompilatorns ansvar att inte tillåta meningslöst kontrollflöde.

    Java har försökt ”lösa” detta problem genom att helt och hållet inte tillåta goto. Med Java kan du dock använda return i ett finally -block och därmed orsaka att ett undantag oavsiktligt sväljs.Samma problem finns fortfarande: kompilatorn gör inte sitt jobb. Att ta bort goto från språket har inte fixat det.

    I C # är goto lika säker som break, continue, try/catch/finally och return. Det låter dig inte använda oinitialiserade variabler, det låter dig inte hoppa ut ur ett slutligt block, etc. Kompilatorn kommer att klaga. Det beror på att det löser det verkliga problemet, vilket är som jag sa meningslöst kontrollflöde. goto avbryter inte magisk bestämd tilldelningsanalys och andra rimliga kompilatorkontroller.

    Kommentarer

    • Din poäng är att C # ’ s goto inte är ond? Om så är fallet är det fallet för varje rutinmässigt använt modernt språk med en goto -konstruktion, inte bara C # …

    Svara

    Ja. När dina loopar är kapslade flera nivåer djupt är goto det enda sättet att elegant bryta sig ur en inre slinga. Det andra alternativet är att ställa in en flagga och bryta ur varje slinga om den flaggan uppfyller ett villkor. Det här är riktigt ful och ganska felbenäget. I dessa fall är goto helt enkelt bättre.

    Naturligtvis gör Java: s märkning break uttalande detsamma men utan att låta dig hoppa till en godtycklig punkt i koden, vilket löser problemet snyggt utan att tillåta saker som gör goto onda.

    Kommentarer

    • goto är aldrig ett elegant svar. När dina slingor är kapslade flera nivåer djupt är ditt problem att du misslyckades med att arkitektera din kod för att undvika flerinterade slingor. Procedursamtal är INTE fienden. (Läs ” Lambda: The Ultimate … ” papper.) Använda en goto för att bryta sig ur öglor kapslade flera nivåer djupt är att sätta ett plåster på en öppen multipelfraktur: det kan vara enkelt men det är inte ’ t rätt svar.
    • Och naturligtvis finns det är aldrig det udda fallet när djupt nestade slingor krävs? Att vara en bra programmerare är inte t bara om att följa reglerna, men också om att veta när man ska bryta mot dem.
    • @ JohnR.Strohm Säg aldrig aldrig. Om du använder termer som ” aldrig ” vid programmering har du ’ tydligt inte behandlat med hörnfall, optimering, resursbegränsningar etc. I djupt kapslade slingor är goto verkligen det renaste och elegantaste sättet att lämna slingorna. ’ spelar ingen roll hur mycket du ’ har omformulerat din kod.
    • @ JohnR.Strohm: näst mest missade funktion vid byte från VB.NET till C #: Do -slingan. Varför? Eftersom jag kan ändra en slinga som behöver en djup brytning till en Do slinga och skriva Exit Do och där ’ är nej GoTo. Kapslade öglor händer hela tiden. Att bryta travarna händer en del% av tiden.
    • @ JohnR.Strohm Den enda anledningen till att du säger ” goto är aldrig ett elegant svar ” beror på att du bestämde dig för att goto aldrig är ett elegant svar, och därför kan alla lösningar som använder goto inte vara ett elegant svar.

    Svar

    Det mesta av modlösheten kommer från en sorts ”religion” som skapats av Gud Djikstra som i början av 60-talet var övertygande om den urskiljande makten att :

    • hoppa var som helst i vilket kodblock
      • -funktion som inte körs från början
      • loopar som inte körs från början
      • hoppad över variabel initialisering
    • hoppa ifrån vilket kodblock som helst utan någon möjlig sanering.

    Detta har inget mer att göra med goto uttalande av de moderna språken, vars existens bara beror på att stödja cr ätning av andra kodstrukturer än de språk som tillhandahålls.

    Speciellt är den första huvudpunkten ovan längre tillåten och den andra rensas (om du goto ett block stacken rullas upp ordentligt och alla korrekta destruktörer kallas)

    Du kan hänvisa detta svar för att få en uppfattning om hur jämn kod inte att använda goto kan vara oläsligt. Problemet är inte att gå själv, utan dålig användning av det.

    Jag kan skriva ett helt program utan att använda if, bara for. Naturligtvis kommer det inte att vara väl läsbart, en look klumpig och onödigt komplicerad.

    Men problemet är inte for. Det är jag.

    Saker som break, continue, throw, bool needed=true; while(needed) {...} osv. noterar mer än maskerad goto för att fly från scimitars av Djikstrarian fanatiker, att – 50 år efter uppfinningen av moderna språk – vill fortfarande ha sina fångar. De glömde vad Djikstra pratade om, de kommer bara ihåg titeln på hans anteckning (GOTO ansågs skadlig, och det var inte ens hans onw titel: det ändrades av redaktören) och skylla och bash, bash och skylla varje konstruktion som har dessa 4 bokstav placerad i sekvens.

    Det är 2011: det är dags att förstå att goto inte har att göra med GOTO uttalande som Djikstra var övertygande om.

    Kommentarer

    • ” Saker som paus, fortsätt , kasta, bool behövs = sant; medan (behövs) {…}, etc. noterar mer än maskerade goto ” Jag håller inte ’ inte med på det. Jag föredrar att ” saker som paus etc är begränsade goto ”, eller något liknande. Det största problemet med att gå är att det vanligtvis är för kraftfullt. I den utsträckning den nuvarande goto är mindre kraftfull än Dijkstra ’ s, är ditt svar bra med mig.
    • @MuhammadAlkarouri: Jag håller helt med. Du hittade bara en bättre formulering för att uttrycka exakt mitt koncept. Min poäng är att dessa begränsningar ibland inte kan tillämpas och att den typ av begränsning du behöver inte finns på språket. Då är en mer ” kraftfull ”, mindre specialiserad, det som gör att du kan lösa problemet. Till exempel är Java break n inte tillgängligt i C ++, därav goto escape, även om escape krävs inte för att bara vara ute från n-slingan.

    Svar

    Den udda goto här eller där, så länge det är lokalt för en funktion, skadar sällan läsbarheten väsentligt. Det gynnar det ofta genom att uppmärksamma att det finns något ovanligt i denna kod som kräver användning av en något ovanlig kontrollstruktur .

    Om (lokala) foton skadar läsbarheten avsevärt är det vanligtvis ett tecken på att funktionen som innehåller bilden har blivit för komplicerad.

    Den senaste bilden jag lade in i bit C-kod var att bygga ett par sammankopplade slingor. Det passar inte in i den normala definitionen av ”acceptabel” användning, men funktionen blev betydligt mindre och tydligare som ett resultat. För att undvika goto skulle ha krävt en särskilt rörig överträdelse av TORR.

    Kommentarer

    • Svaret på detta anges mest i den gamla ” Lay ’ s Potatischips ” slogan: ” Satsa att du inte kan ’ inte äta en ”. I ditt exempel har du två ” sammankopplade ” (vad det än betyder och jag ’ Jag slår vad om att det inte är ’ t snyggt) loopar, och gotoen gav dig en billig ut. Vad sägs om underhållskillen, som måste ändra koden efter att du träffats av en buss? Kommer det att göra hans liv enklare eller svårare? Behöver dessa två slingor omprövas?

    Svar

    Jag tror att hela denna fråga har varit ett fall av skällande fel träd.

    GOTO som sådan verkar inte problematisk för mig, utan snarare är det mycket ofta ett symptom på en verklig synd: spaghettikod.

    Om GOTO orsakar större korsning av flödeskontrolllinjer är det dåligt, punkt. Om det inte passerar några flödeskontrolllinjer är det ofarligt. I den grå zonen däremellan har vi saker som loop-bailouts, det finns fortfarande några språk som inte har lagt till konstruktioner som täcker alla legitima gråfall.

    Det enda fallet jag har befunnit mig att faktiskt använda det på många år är fallet med slingan där beslutpunkten ligger mitt i slingan. Du har antingen duplicerad kod, en flagga eller en GOTO. Jag tycker att GOTO-lösningen är den bästa av de tre. Det finns ingen korsning av flödeskontrolllinjer här, det är ofarligt.

    Kommentarer

    • Fallet du hänvisar till kallas ibland ”loop and a half” eller ”N plus one half loop” och det är ett känt användningsfall för goto som hoppar in i en slinga (om språket tillåter detta; eftersom det andra fallet är att hoppa ur slingan i mitten är det vanligtvis trivialt utan goto
    • (Ack, de flesta språk förbjuder att hoppa i en slinga.)
    • @KonradRudolph: Om du implementerar ” loop ” med GOTO finns det ingen annan loopstruktur att hoppa in i.
    • Jag tänker på goto som att skrika KONTROLLFLÖDET HÄR INTE ’ T FIT NORMAL STRUKTURERAD-PROGRAMMERING MÖNSTER . Eftersom kontrollflöden som passar strukturerade programmeringsmönster är lättare att resonera om än de som inte ’ t, bör man försöka använda sådana mönster när det är möjligt; om koden inte passar sådana mönster bör man inte ’ t skrika att den inte ’ t. Å andra sidan, i fall där koden verkligen inte ’ inte passar sådana mönster, kan det vara bättre att skrika om det än att låtsas att koden passar när den verkligen inte ’ t.
    • @supercat Tänk, du skrev själv ett schema och sedan blåser vinden ut det ur dina händer. Enligt din logik ska du inte ’ inte hämta det, för att jaga efter ditt schema stod inte ’ t på ditt schema.

    Svar

    Ja, goto kan användas för att gynna utvecklarens upplevelse: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

    Men precis som med alla kraftfulla verktyg (pekare, flera arv etc.) måste man vara disciplinerad använder det. Exemplet i länken använder PHP, vilket begränsar användningen av goto-konstruktionen till samma funktion / metod och inaktiverar möjligheten att hoppa in i ett nytt kontrollblock (t.ex. loop, switch statement, etc.)

    Svar

    Beror på språket. Den används fortfarande ofta i Cobol-programmering, till exempel. Jag har också arbetat på en Barionet 50-enhet, vars programmeringsspråk för firmware är en tidig grundläggande dialekt som naturligtvis kräver att du använder Goto.

    Svar

    goto kan vara användbart när du överför äldre samlarkod till C. I första hand kan en instruktions- med instruktionsomvandling till C, med goto som en ersättning för montering ”s branch instruktion, kan möjliggöra mycket snabb portering.

    Kommentarer

    • Korrekt, men ett av argumenten mot goto s är att de motverkar kompilatoroptimeringar.
    • @Sapphire_Brick: Många kompilatoroptimeringar är utformade kring vissa exekveringsmönster. Om uppgiften som ska utföras ’ inte passar de exekveringsmönster som stöds, ” motverkande ” optimeringar kanske inte vara en dålig sak.

    Svar

    Jag skulle argumentera nej. De bör alltid ersättas med ett verktyg som är mer specifikt för problemet som goto används för att lösa (såvida det inte finns tillgängligt på ditt språk). Till exempel, bryt uttalanden och undantag för att lösa tidigare goto-lösta problem med att slinga och felhantering.

    Kommentarer

    • Jag ’ d argumenterar att när språk har båda dessa funktioner är goto vanligtvis frånvarande från dessa språk.
    • Men beror det på att de inte ’ t behöver dem, eller för att människor tror att de inte ’ t behöver dem?
    • Dina åsikter är stora. Det finns många fall när goto är det som ligger närmast själva problemdomänens semantik, allt annat skulle vara ett smutsigt hack.
    • @ SK-logik: Jag gör inte ’ tänk inte att ordet ” bigoted ” betyder vad du tycker det betyder.
    • @Keith,

    intolerant hängiven till sina egna åsikter och fördomar ” – att ’ är vad jag konsekvent observera här, med detta goto-bashing ögonbindel mycket. ” Bör alltid bytas ut ” är fanatiska ’ s ord åtminstone. Ingenting nära en ordentlig, sund åsikt, utan bara en ren överdrift. Denna ” alltid ” lämnar inget utrymme för någon alternativ åsikt, se?

    Svar

    Jag skulle säga nej. Om du hittar behovet av att använda GOTO, kommer jag att satsa på att det finns ett behov av att omforma koden.

    Kommentarer

    • Kanske, men du haven ’ t gav något resonemang
    • Dijkstra gav resonemanget i detalj för årtionden sedan.
    • Just Dogma. Inga resoner. Obs! Djikstra är INTE MER GILTIGT RESON: det hänvisade till BASIC- eller FORTRAN GOTO-uttalandet i de tidiga ’ 60-talet. De har ingenting att göra med de riktigt anemiska (jämfört med kraften hos dessa) dagens bilder.
    • @EmilioGaravaglia Nåväl, den del av hans resonemang som fortfarande gäller idag är att det ’ är väldigt lätt att skriva spagettikod genom att använda vägen till många foton. Men enligt den logiken borde vi inte ’ inte använda pekare för att använda så många pekare som number of gotos needed to create problems skulle skapa liknande kaos.

    Lämna ett svar

    Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *