goto
frarådes nesten universelt. Bruker du denne uttalelsen noen gang?
Kommentarer
Svar
Dette har blitt diskutert flere ganger på Stack Overflow, og Chris Gillum oppsummerte mulige bruksområder for goto
:
Avslutt en funksjon
Ofte i en funksjon kan du tildele ressurser og trenger å avslutte flere steder. Programmører kan forenkle koden ved å sette ressursoppryddingskoden på slutten av funksjonen alle » utgangspunkter » av funksjonen ville gå oppryddingsetiketten. På denne måten trenger du ikke skrive oppryddingskode ved hvert » utgangspunkt » av funksjonen.
Avslutte nestede sløyfer
Hvis du er i en nestet løkke og trenger å bryte ut av alle sløyfer, en goto kan gjøre dette mye renere og enklere enn pauseuttalelser og if-checks.
Lavt ytelsesforbedringer
Dette er bare gyldig i perf-kritisk kode, men goto-uttalelser kjøres veldig raskt og kan gi deg et løft når du går gjennom en funksjon. Dette er et tokantet sverd, men fordi en kompilator vanligvis ikke kan optimalisere koden som inneholder bilder.
Jeg vil argumentere, slik mange andre vil hevde , at i alle disse tilfellene blir bruken av goto
brukt som et middel for å komme seg ut av et hjørne man kodet seg inn i, og er generelt et symptom på kode som kan omformes .
Kommentarer
- Det første problemet løses veldig pent av
finally
blokker på moderne språk, og det andre løses av merketbreak
s. Hvis du ‘ sitter fast med C, mengoto
er stort sett den eneste måten å løse disse problemene elegant på. - Veldig gode poeng. Jeg liker hvordan Java tillater å bryte ut av flere løkkerivåer
- @Chinmay – til slutt bare gjelder for 1) moderne språk som har dem og b) du tåler overhead (unntakshåndtering har en overhead. ) Det vil si at bruk av
finally
bare er gyldig under disse forholdene. Det er veldig sjeldne, men likevel gyldige situasjoner der en gåtur er veien å gå. - Ok, folk … hva pokker er forskjellen mellom
break 3
ellerbreak myLabel
oggoto myLabel
. Å det ‘ er akkurat nøkkelordet. Hvis du brukerbreak
,continue
eller et lignende nøkkelord, blir du kjent med etgoto
(Hvis du brukerfor, while, foreach, do/loop
bruker du en betinget goto.) - Om ytelse på lavt nivå – det kan være vanskelig å forutsi oppførselen til moderne prosessor (pipeline, utføring av ordre) så sannsynligvis er det ikke verdt det i 99% av tilfellene, eller det kan til og med være tregere. @MatthewWhited: Omfang. Hvis du går inn i omfanget på et vilkårlig punkt, er det ikke klart (for menneskelig) hva konstruktører skal kalles (problemet eksisterer også i C).
Svar
Kontrollflytkonstruksjoner på høyere nivå har en tendens til å tilsvare konsepter i problemdomenet. En hvis / annet er en beslutning basert på en eller annen tilstand. En løkke sier å utføre noen handlinger gjentatte ganger. Selv en pauseuttalelse sier «vi gjorde dette gjentatte ganger, men nå må vi stoppe».
En goto-uttalelse, derimot, har en tendens til å tilsvare et konsept i det kjørende programmet, ikke i problem domene. Det står å fortsette kjøringen på et spesifisert punkt i programmet . Noen som leser koden må utlede hva det betyr med hensyn til problemdomenet.
Selvfølgelig kan alle konstruksjoner på høyere nivå defineres i form av bilder og enkle betingede grener . Det betyr ikke at de bare er i forkledning. Tenk på dem som begrensede bilder – og det er begrensningene som gjør dem nyttige. En pauseuttalelse er implementert som et hopp til slutten av den vedlagte sløyfen, men det er bedre tenkt som fungerer på løkken som helhet.
Alt annet er lik, kode hvis struktur gjenspeiler den for problemdomenet, har en tendens til å være lettere å lese og vedlikeholde.
Det er ingen tilfeller der det kreves absolutt en uttalelse (det er «s en teorem om det), men det er tilfeller der det kan være den minst dårlige løsningen. Disse tilfellene varierer fra språk til språk, avhengig av hvilke høyere nivåkonstruksjoner språket støtter.
I C, for eksempel, tror jeg det er tre grunnleggende scenarier der en goto er passende.
- Å bryte ut av en nestet sløyfe. Dette ville være unødvendig hvis språket hadde en merket pauseuttalelse.
- Å sperre ut av en kodestrekning (vanligvis en funksjonsdel) i tilfelle en feil eller annen uventet hendelse . Dette ville være unødvendig hvis språket hadde unntak.
- Implementering av en eksplisitt endelig statsmaskin. I dette tilfellet (og, tror jeg, bare i dette tilfellet) tilsvarer en rett direkte til et konsept i problemdomenet, og overgår fra en tilstand til en spesifisert annen tilstand, der den nåværende tilstanden er representert av hvilken kodeblokk som for tiden utføres .
På den annen side kan en eksplisitt endelig tilstandsmaskin også implementeres med en bryteruttalelse i en løkke. Dette har fordelen at hver stat starter på samme sted i koden, noe som for eksempel kan være nyttig for feilsøking.
Hovedbruken av en goto på et rimelig moderne språk (en som støtter hvis / else and loops) er å simulere en kontrollflytekonstruksjon som mangler fra språket.
Kommentarer
- Dette er faktisk det beste svaret så langt – ganske overraskende, for et spørsmål som er halvannet år gammelt. 🙂
- +1 til » hittil beste svaret «. — » Hovedbruken av en goto på et rimelig moderne språk (en som støtter hvis / annet og løkker) er å simulere en kontrollflyt konstruer at ‘ mangler fra språket. »
- I bryteruttalelses tilstandsmaskin, hver skriv til kontrollverdi er virkelig en
goto
. SSSM ‘ s er ofte gode strukturer å bruke, siden de ser parater SM-tilstanden fra utførelseskonstruksjonen, men de ‘ t eliminerer virkelig » bilder «. - » Alt annet er lik, kode hvis struktur gjenspeiler den for problemdomenet, har en tendens til å være lettere å lese og vedlikeholde. div id = «877889c4e5»>
Jeg ‘ har visst dette lenge, men manglet ordene for å så presist kommunisere det på en måte som andre programmerere kan og vil faktisk forstå. Takk for dette.
Svar
Det kommer helt sikkert an på programmeringsspråket. Hovedårsaken til at goto
har vært kontroversiell, er på grunn av de dårlige effektene som oppstår når kompilatoren lar deg bruke den for liberalt. Problemer kan oppstå, for eksempel hvis det lar deg bruke goto
på en slik måte at du nå kan få tilgang til en uinitialisert variabel, eller verre, for å hoppe inn i en annen metode og rote med samtalen stable. Det bør være kompilatorens ansvar å ikke tillate meningsløs kontrollflyt.
Java har forsøkt å «løse» dette problemet ved å ikke tillate goto
helt. Imidlertid lar Java deg bruke return
inne i en finally
-blokk og dermed føre til at et unntak svelges utilsiktet.Det samme problemet er fremdeles der: kompilatoren gjør ikke jobben sin. Å fjerne goto
fra språket har ikke fikset det.
I C # er goto
like trygt som break
, continue
, try/catch/finally
og return
. Det lar deg ikke bruke uinitialiserte variabler, det lar deg ikke hoppe ut av en endelig blokk, etc. Kompilatoren vil klage. Dette er fordi det løser ekte problemet, som er som jeg sa meningsløs kontrollflyt. goto
avbryter ikke magisk analyse av bestemte oppgaver og andre rimelige kompilatorkontroller.
Kommentarer
- Poenget ditt er at C # ‘ s
goto
ikke er ondt? I så fall er det tilfelle for alle rutinemessig brukte moderne språk med engoto
-konstruksjon, ikke bare C # …
Svar
Ja. Når løkkene dine er nestet flere nivåer dypt, er goto
den eneste måten å elegant bryte ut av en indre sløyfe. Det andre alternativet er å sette et flagg og bryte ut av hver løkke hvis det flagget tilfredsstiller en betingelse. Dette er veldig stygt, og ganske feilutsatt. I disse tilfellene er goto
rett og slett bedre.
Selvfølgelig gjør Java s merkede break
uttalelse det samme ting, men uten å la deg hoppe til et vilkårlig punkt i koden, som løser problemet pent uten å tillate ting som gjør goto
onde.
Kommentarer
- goto er aldri et elegant svar. Når løkkene dine er nestet flere nivåer dypt, er problemet at du ikke klarte å arkitere koden din for å unngå de flerinteresserte løkkene. fienden. (Les » Lambda: The Ultimate … » papirer.) Bruke en goto for å bryte ut av løkker nestet flere nivåer dyp er å sette et plaster på et åpent multipelt brudd: det kan være enkelt, men det er ikke ‘ t det riktige svaret.
- Og selvfølgelig, der er aldri det merkelige tilfellet når det kreves dype nestede sløyfer? Å være en god programmerer er ikke t bare om å følge reglene, men også om å vite når du skal bryte dem.
- @ JohnR.Strohm Si aldri aldri. Hvis du bruker ord som » aldri » i programmering, har du ‘ tydeligvis ikke behandlet med hjørnesaker, optimalisering, ressurskontroller osv. I dypt nestede løkker er goto veldig mye den reneste, elegante måten å gå ut av løkkene. Spiller ikke ‘ hvor mye du ‘ har omformulert koden din.
- @ JohnR.Strohm: nest mest savnet funksjon ved å bytte fra VB.NET til C #:
Do
loop. Hvorfor? Fordi jeg kan endre den ene sløyfen som trenger en dyp pause i enDo
sløyfe og skriveExit Do
og der ‘ er neiGoTo
. Nestede sløyfer skjer hele tiden. Å bryte stablene skjer en del% av tiden. - @ JohnR.Strohm Den eneste grunnen til at du sier » goto er aldri et elegant svar » er fordi du bestemte deg for at goto aldri er et elegant svar, og derfor kan enhver løsning som bruker goto ikke være et elegant svar.
Svar
Det meste av motløsheten kommer fra en slags «religion» som er blitt skapt over Gud Djikstra som var overbevisende tidlig på 60-tallet om den vilkårlige makten til :
- hopp hvor som helst inn i hvilken kodeblokk
- -funksjon som ikke er utført fra begynnelsen
- sløyfer som ikke er utført fra begynnelsen
- hoppet over variabel initialisering
- hopp vekk fra hvilken som helst blokk med kode uten mulig opprydding.
Dette har ikke mer å gjøre med goto
uttalelse av moderne språk, hvis eksistens bare skyldes støtte til cr sporing av andre kodestrukturer enn språket.
Spesielt er det første hovedpunktet ovenfor tillatt lenger, og det andre blir renset (hvis du goto
en blokk stabelen er utrullet ordentlig og alle riktige destruktorer kalles)
Du kan se dette svaret for å få en ide om hvor jevn kode ikke er bruk av goto kan være uleselig. Problemet er ikke å gå i seg selv, men dårlig bruk av det.
Jeg kan skrive et helt program uten å bruke if
, bare for
. Selvfølgelig vil det ikke være godt lesbart, et blikk klønete og unødvendig komplisert.
Men problemet er ikke for
. Det er meg.
Ting som break
, continue
, throw
, bool needed=true; while(needed) {...}
osv. merker seg mer enn maskerade goto
for å flykte vekk fra scimitars av de djikstrariske ildsjelene, at – 50 år etter oppfinnelsen av moderne språk – vil fortsatt ha fangene sine. De glemte hva Djikstra snakket om, de husker bare tittelen på notatet hans (GOTO ansett som skadelig, og det var ikke engang hans onw-tittel: det ble endret av redaktøren) og skyld og bash, bash og skyld hver konstruksjon som har disse bokstav plassert i rekkefølge.
Det er 2011: det er på tide å forstå at goto
ikke har å gjøre med GOTO
uttalelse Djikstra var overbevisende om.
Kommentarer
- » Ting som pause, fortsett , kast, bool nødvendig = sant; mens (nødvendig) {…} osv. merker seg mer enn maskerade til » Jeg er ikke ‘ ikke enig i det. Jeg foretrekker at » ting som pause etc er begrenset til «, eller noe sånt. Hovedproblemet med å gå er at det vanligvis er for kraftig. I den grad den nåværende retningen er mindre kraftfull enn Dijkstra ‘ s, er svaret ditt bra med meg.
- @MuhammadAlkarouri: Jeg er helt enig. Du fant nettopp en bedre formulering for å uttrykke akkurat konseptet mitt. Poenget mitt er at disse begrensningene noen ganger ikke kan gjelde, og den begrensningen du trenger ikke er på språket. Så er en mer » kraftig «, mindre spesialisert, det som gjør at du kan løse problemet. For eksempel er Java
break n
ikke tilgjengelig i C ++, deravgoto escape
, selv omescape
er ikke påkrevd å være bare utenfor n-sløyfen.
Svar
Den rare oddsen her eller der, så lenge det er lokalt for en funksjon, skader sjelden lesbarheten betydelig. Det gagner det ofte ved å gjøre oppmerksom på at det er noe uvanlig som skjer i denne koden som krever bruk av en noe uvanlig kontrollstruktur .
Hvis (lokale) bilder skader lesbarheten betydelig, er det vanligvis et tegn på at funksjonen som inneholder goto har blitt for kompleks.
Den siste gotoen jeg la inn i stykke C-kode var å bygge et par sammenlåsende sløyfer. Det passer ikke inn i den normale definisjonen av «akseptabel» bruk av goto, men funksjonen endte opp betydelig mindre og tydeligere som et resultat. For å unngå goto ville det ha krevd et spesielt rotete brudd på TØR.
Kommentarer
- Svaret på dette er mest pithy angitt i den gamle » Lay ‘ s Potetgull » slagord: » Satser på at du ikke kan ‘ t spise bare en «. I eksempelet ditt har du to » sammenlåsende » (hva det enn betyr, og jeg ‘ Jeg satser på at det ikke er ‘ t vakker) sløyfer, og gotoen ga deg en billig ut. Hva med vedlikeholds fyren, som må endre den koden etter at du ble truffet av en buss? Kommer det å gjøre livet hans lettere eller vanskeligere? Må disse to sløyfene vurderes på nytt?
Svar
Jeg tror hele dette problemet har vært et tilfelle av bjeffing feil tre.
GOTO som sådan virker ikke problematisk for meg, men snarere er det veldig ofte et symptom på en faktisk synd: spaghettikode.
Hvis GOTO forårsaker større kryssing av strømningskontrolllinjer så er det dårlig, punktum. Hvis det ikke krysser noen flytkontrolllinjer, er det ufarlig. I den grå sonen innimellom har vi ting som bailouts for loop, det er fortsatt noen språk som ikke har lagt til konstruksjoner som dekker alle legitime grå tilfeller.
Det eneste tilfellet jeg faktisk har funnet det å bruke på mange år er tilfellet med løkken der avgjørelsespunktet er midt i løkken. Du sitter igjen med enten duplisert kode, et flagg eller en GOTO. Jeg finner GOTO-løsningen den beste av de tre. Det er ingen krysning av strømningskontrolllinjer her, den er ufarlig.
Kommentarer
- Saken du henviser til blir noen ganger kalt «loop and a half» eller «N plus one half loop» og det er et kjent brukstilfelle for
goto
s som hopper inn i en løkke (hvis språket tillater dette; siden det andre tilfellet, å hoppe ut av løkken i midten, er vanligvis trivielt utengoto
- (Alas, de fleste språk forbyr å hoppe i en løkke.)
- @KonradRudolph: Hvis du implementerer » loop » med GOTO er det ingen annen sløyfestruktur å hoppe inn i.
- Jeg tenker på
goto
som å rope KONTROLLSTRØMMEN HER
T FIT NORMAL STRUKTURERT-PROGRAMMERING MØNSTER . Fordi kontrollflyter som passer strukturerte programmeringsmønstre er lettere å resonnere enn de som ikke ‘ t, bør man prøve å bruke slike mønstre når det er mulig; hvis koden ikke passer til slike mønstre, bør man ikke ‘ t rope at den ikke ‘ t. På den annen side, i tilfeller der koden ikke ‘ ikke passer til slike mønstre, kan det være bedre å rope om det enn å late som koden passer når den virkelig ikke ‘ t.
Svar
Ja, gotoen kan brukes til å dra nytte av utviklerens opplevelse: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/
Men som med alle kraftige verktøy (pekere, flere arv osv.), må man være disiplinert bruker det. Eksemplet i lenken bruker PHP, som begrenser bruken av goto-konstruksjonen til samme funksjon / metode og deaktiverer muligheten til å hoppe inn i en ny kontrollblokk (f.eks. Loop, switch statement osv.)
Svar
Avhenger av språket. Det er fortsatt mye brukt for eksempel i Cobol-programmering. Jeg har også jobbet på en Barionet 50-enhet, hvis programmeringsspråk for firmware er en tidlig BASIC-dialekt som selvfølgelig krever at du bruker Gå.
Svar
goto
kan være nyttig når du porterer eldre samlekode til C. I første omgang kan en instruks- konvertering av instruksjon til C, ved å bruke goto
som erstatning for montøren «s branch
instruksjon, kan muliggjøre veldig rask portering.
Kommentarer
- Riktig, men et av argumentene mot
goto
s er at de hindrer kompilatoroptimaliseringer. - @Sapphire_Brick: Mange kompilatoroptimaliseringer er designet rundt bestemte kjøringsmønstre. Hvis oppgaven som skal utføres ikke ‘ ikke passer til de støttede kjøringsmønstrene, » motvirkning av » optimaliseringer kan hende at ikke være en dårlig ting.
Svar
Jeg vil hevde nei. De bør alltid erstattes med et verktøy som er mer spesifikt for problemet goto blir brukt til å løse (med mindre det ikke er tilgjengelig på ditt språk). For eksempel bryter utsagn og unntak til tidligere goto-løste problemer med sløyfe som slipper ut og feilhåndtering.
Kommentarer
- Jeg ‘ d hevder at når språk har begge deler disse funksjonene er
goto
vanligvis fraværende fra disse språkene. - Men er det fordi de ikke ‘ t trenger dem, eller fordi folk tror de ikke ‘ ikke trenger dem?
- Dine synspunkter er store. Det er mange tilfeller når
goto
er den nærmeste tingen til det aller mest problematiske domenesemantikken. Alt annet vil være en skitten hack. - @ SK-logikk: Jeg don ‘ t tror ordet » bigoted » betyr hva du tror det betyr.
- @Keith,
intolerant viet til sine egne meninger og fordommer » – at ‘ er det jeg konsekvent observere her, med dette goto-bashing bind for øynene. » Skal alltid erstattes » er fanatiske ‘ s ord, i det minste. Ingenting i nærheten av en skikkelig, sunn mening, men bare en ren fordømmelse. Denne » alltid » gir ikke plass til noen alternativ mening, ser du?
Svar
Jeg vil si nei. Hvis du finner behovet for å bruke GOTO, vil jeg satse på at det er et behov for å redesigne koden.
Kommentarer
- Kanskje, men du haven ‘ t ga noen resonnement
- Dijkstra ga resonnementet, i detalj, for flere tiår siden.
- Bare Dogma. Ingen resoner. Merk: Djikstra er IKKE MER GJELDIG RESON: den refererte til BASIC- eller FORTRAN GOTO-uttalelsen i den tidlige ‘ 60-tallet. De har ingenting å gjøre med den virkelig anemiske (sammenlignet med kraften til disse) dagene.
- @EmilioGaravaglia Vel, den delen av hans resonnement som fremdeles gjelder i dag er at det ‘ er veldig enkelt å skrive spaghettikode ved å bruke veien til mange bilder. Imidlertid, etter den logikken, bør vi ikke ‘ ikke bruke pekere fordi bruk av så mange pekere som
number of gotos needed to create problems
ville skape lignende kaos.
goto
er hva CPUen til syvende og sist gjør, men det fungerer ikke bra med det mennesker trenger å forstå og abstrakte på grunn av at det ikke er noe merke på målet slutt. Sammenlign med IntercalCOMEFROM
.goto
ikke nødvendig. Det er bare den mest rasjonelle måten å implementere dem på de tvingende språkene, siden det er det nærmeste som den somantiske statsovergangen. Og destinasjonen kan være ganske langt fra kilden, den vil ‘ ikke hindre lesbarheten. Mitt favoritteksempel på en slik kode er D.E. Knuth ‘ s implementering av eventyrspillet.