goto se téměř všeobecně nedoporučuje. Je použití tohoto prohlášení někdy užitečné?

Komentáře

  • xkcd.com/292
  • goto je to, co CPU nakonec dělá, ale nefunguje dobře s tím, co lidé potřebují pochopit a abstrahovat, protože na cíli není žádná značka konec. V porovnání s Intercal COMEFROM.
  • @Thorbj ø rnRavnAndersen, co ještě lidé myslí, když ‚ hovoříte o přechodech stavu ve stavovém automatu? Nevidíte ‚ podobnost? “ Přejít na daný stav „, který ‚ Co to znamená a cokoli jiného by nebylo nic jiného než zbytečná komplikace takové triviální věci. A co myslíte tím “ bez označení „? Štítek je taková značka.
  • @ SK-logic, záleží na tom, jak daleko umožníte, aby goto ‚ s pocházelo. Státní stroje nevyžadují implementaci goto.
  • @Thorbj ø rnRavnAndersen, samozřejmě goto není vyžadován. Je to jen nejracionálnější způsob jejich implementace v imperativních jazycích, protože je to nejblíže samotné sémantice přechodu státu. A jeho cíl může být docela daleko od zdroje, nebude bránit ‚ čitelnosti. Můj oblíbený příklad takového kódu je D.E. Knuth ‚ implementace hry Adventure.

Odpověď

O tom bylo několikrát diskutováno na přetečení zásobníku a Chris Gillum shrnul možná použití goto :

Čisté ukončení funkce

Často ve funkci můžete přidělit zdroje a musíte ukončit na více místech. Programátoři mohou svůj kód zjednodušit tak, že na konec funkce umístí kód pro vyčištění prostředku, takže všechny “ výstupní body “ funkce přejdou štítek čištění. Tímto způsobem nemusíte psát čisticí kód v každém “ výstupním bodě “ funkce.

Ukončení vnořených smyček

Pokud jste ve vnořené smyčce a potřebujete se vymanit z all smyčky, goto to může udělat mnohem čistší a jednodušší než příkazy break a if-checks.

Vylepšení výkonu na nízké úrovni

Toto je platné pouze v perf-critical kódu, ale příkazy goto se provádějí velmi rychle a mohou vám při procházení funkcí pomoci. Toto je meč s dvojitým ostřím, protože kompilátor obvykle nemůže optimalizovat kód, který obsahuje gotos.

Tvrdím, jak by argumentovalo mnoho dalších , že ve všech těchto případech se použití goto používá jako prostředek k vymanění se z rohu, do kterého se člověk sám zakóduje, a je obecně příznakem kódu, který lze refaktorovat .

Komentáře

  • První problém je velmi úhledně vyřešen bloky finally v moderních jazycích a druhý je vyřešen štítkem break s. Pokud ‚ uvíznete na C, goto je do značné míry jediný způsob, jak elegantně vyřešit tyto problémy.
  • Velmi dobré body. Líbí se mi, jak Java umožňuje vymanit se z více úrovní smyček
  • @Chinmay – konečně blokuje pouze platí pro 1) moderní jazyky, které je mají ab) můžete tolerovat režii (zpracování výjimek má režii. ) To znamená, že použití finally je platné pouze za těchto podmínek. Existují velmi vzácné, ale platné situace, kdy je cesta správná.
  • Dobře, lidi … jaký je sakra rozdíl mezi break 3 nebo break myLabel a goto myLabel. To je ‚ správné právě klíčové slovo. Pokud používáte break, continue nebo podobné klíčové slovo, používáte goto (Pokud používáte for, while, foreach, do/loop používáte podmíněné goto.)
  • O nízkoúrovňovém výkonu – chování moderního procesoru může být obtížné předvídat (pipeline, out-of-order execution), takže pravděpodobně v 99% případů to nestojí za to, nebo dokonce může být pomalejší. @ MatthewWhited: Scoping. Pokud zadáte obor v libovolném bodě, není jasné (člověku), jak se mají konstruktory nazývat (problém existuje také v C).

Odpověď

Konstrukce toku řízení na vyšší úrovni mají tendenci odpovídat konceptům v problémové doméně. If / else je rozhodnutí založené na nějaké podmínce. Smyčka říká opakovat nějakou akci. I příkaz break říká: „Dělali jsme to opakovaně, ale nyní musíme přestat.“

Na druhou stranu příkaz goto má tendenci odpovídat konceptu v běžícím programu, nikoli v problémová doména. Říká, že pokračovat v provádění v zadaném bodě v programu . Někdo, kdo čte kód, musí odvodit , co to znamená s ohledem na problémovou doménu.

Všechny konstrukty na vyšší úrovni lze samozřejmě definovat pomocí gotos a jednoduchých podmíněných větví . To neznamená, že jsou pouze v přestrojení. Přemýšlejte o nich jako o omezeném gotosu – a právě díky omezením jsou užitečná. Příkaz break je implementován jako skok na konec obklopující smyčky, ale je lepší jej považovat za fungující na smyčce jako celek.

Pokud je vše ostatní stejné, kód, jehož struktura odráží strukturu problémové domény, má tendenci být snazší číst a udržovat.

Neexistují žádné případy, kdy příkaz goto je absolutně vyžadován (v tomto smyslu existuje věta ), ale existují případy, kdy to může být nejméně špatné řešení. Tyto případy se liší od jazyk na jazyk, v závislosti na tom, jaké konstrukce na vyšší úrovni jazyk podporuje.

Například v jazyce C se domnívám, že existují tři základní scénáře, kde je vhodné goto.

  1. Vyřazení z vnořené smyčky. To by bylo zbytečné, pokud by jazyk obsahoval příkaz break s označením.
  2. Vypomáhání z části kódu (obvykle těla funkce) v případě chyby nebo jiné neočekávané události . To by bylo zbytečné, pokud by jazyk měl výjimky.
  3. Implementace explicitního konečného stavového automatu. V tomto případě (a myslím, že pouze v tomto případě) goto odpovídá přímo konceptu v problémové doméně, přechodu z jednoho stavu do zadaného jiného stavu, kde aktuální stav je reprezentován tím, který blok kódu aktuálně provádí .

Na druhou stranu lze explicitní stroj s konečným stavem implementovat také pomocí příkazu switch uvnitř smyčky. To má tu výhodu, že každý stav začíná v kódu na stejném místě, což může být užitečné například pro ladění.

Hlavní použití goto v přiměřeně moderním jazyce (ten, který podporuje if / else and loops) je simulovat konstrukt toku řízení, který jazyku chybí.

Komentáře

  • Toto je dosud nejlepší odpověď – docela překvapivé, na otázku starou jeden a půl roku. 🙂
  • +1 až “ zatím nejlepší odpověď „. — “ Hlavní použití goto v přiměřeně moderním jazyce (ten, který podporuje if / else a smyčky) je simulovat tok řízení vytvořte, že ‚ chybí jazyku. “
  • Ve stavovém automatu switch-statement každý zápis do kontrolní hodnota je opravdu goto. SSSM ‚ s jsou často dobrou strukturou, protože se používají parate out the SM state from the execution construct, but they don ‚ t opravdu eliminovat “ gotos „.
  • “ Pokud jsou všechny ostatní stejné, kód, jehož struktura odráží strukturu problémové domény, má tendenci být snazší číst a udržovat. “ Z ‚ jsem to dlouho věděl úplně, ale chyběla mi slova, abych to tak přesně sdělil způsobem, který ostatní programátoři mohou a budou skutečně rozumět. Děkuji za to.
  • Věta o “ strukturovaném programu “ mě baví, protože má tendenci jasně demonstrovat poukazují na to, že použití strukturovaných programovacích příkazů k emulaci goto je mnohem méně čitelné než pouhé použití goto!

Answer

Určitě to záleží na programovacím jazyce. Hlavní důvod, proč je goto kontroverzní, je kvůli jeho nepříznivým účinkům, které vznikají, když jej kompilátor umožňuje používat příliš liberálně. Mohou nastat problémy, například pokud vám umožní použít goto takovým způsobem, že nyní můžete přistupovat k neinicializované proměnné nebo v horším případě skočit na jinou metodu a pokazit se s hovorem zásobník. Mělo by být odpovědností kompilátoru zakázat nesmyslný řídicí tok.

Java se pokusila tento problém „vyřešit“ úplným zakázáním goto. Java vám však umožňuje použít return uvnitř bloku finally a způsobit tak nechtěné spolknutí výjimky.Stejný problém stále existuje: kompilátor nedělá svou práci. Odstranění goto z jazyka to neopravilo.

V jazyce C # je goto stejně bezpečný jako break, continue, try/catch/finally a return. Nedovolí vám používat neinicializované proměnné, nedovolí vám vyskočit z konečného bloku atd. Kompilátor si bude stěžovat. Je to proto, že řeší skutečný problém, který je, jak jsem řekl, nesmyslný kontrolní tok. goto magicky nezruší analýzu definitivního přiřazení a další přiměřené kontroly kompilátoru.

Komentáře

  • Jde o to, že C # ‚ s goto není zlo? Pokud ano, je tomu tak pro každý běžně používaný moderní jazyk s konstrukcí goto, nejen C # …

Odpověď

Ano. Když jsou vaše smyčky vnořeny do několika úrovní hluboko, goto je jediný způsob, jak se elegantně vymanit z vnitřní smyčky. Druhou možností je nastavit příznak a vylomit každou smyčku, pokud tento příznak splňuje podmínku. To je opravdu ošklivé a docela náchylné k chybám. V těchto případech je goto jednoduše lepší.

Samozřejmě, prohlášení Java označené break dělá totéž věc, ale bez toho, abyste vám umožnili přeskočit na libovolné místo v kódu, což problém úhledně vyřeší, aniž byste povolili věci, které dělají goto zlo.

Komentáře

  • goto nikdy není elegantní odpovědí. Když jsou vaše smyčky vnořeny do několika úrovní hluboko, vaším problémem je, že se vám nepodařilo vytvořit svůj kód, abyste se vyhnuli vícenásobným smyčkám. Volání procedur NENÍ nepřítel. (Přečtěte si “ Lambda: The Ultimate … „). Pomocí goto k vymanění se ze smyček vnořilo několik levels deep dává band-aid na otevřenou zlomeninu: může to být jednoduché, ale není to ‚ správná odpověď.
  • A samozřejmě, existuje není nikdy zvláštní případ, kdy jsou požadovány hluboce vnořené smyčky? Být dobrým programátorem není nejde jen o dodržování pravidel, ale také o to, kdy vědět, kdy je porušit.
  • @ JohnR.Strohm Nikdy neříkej nikdy. Pokud v programování používáte výrazy jako “ nikdy „, ‚ zjevně nedojde s rohovými případy, optimalizací, kontrakcemi zdrojů atd. V hluboce vnořených smyčkách je goto opravdu ten nejčistší a nejelegantnější způsob, jak smyčky opustit. Nezáleží ‚ na tom, jak moc jste ‚ přeformátovali svůj kód.
  • @ JohnR.Strohm: Druhý nejvíce zmeškaný funkce při přechodu z VB.NET na C #: smyčka Do. Proč? Protože můžu změnit jednu smyčku, která potřebuje hluboký zlom do smyčky Do a zadat Exit Do a tam ‚ s no GoTo. Vnořené smyčky se dějí pořád. K rozbití hromádek dochází někdy% času.
  • @ JohnR.Strohm Jediným důvodem, proč říkáte “ goto, nikdy není elegantní odpověď “ je to proto, že jste se rozhodli, že goto nikdy není elegantní odpovědí, a proto jakékoli řešení používající goto nemůže být elegantní odpovědí.

odpověď

Většina odrazování pochází z jakési „náboženství“, které bylo vytvořeno na základě boha Djikstra, které na počátku 60. let přesvědčilo o své nevybíravé moci :

  • skočit kamkoli do jakéhokoli bloku kódu
    • funkce, která nebyla provedena od začátku
    • smyčky, které nebyly provedeny od začátku,
    • přeskočená inicializace proměnné
  • skok od jakéhokoli bloku kódu bez jakéhokoli možného vyčištění.

To už nemá nic společného s goto prohlášení moderních jazyků, jejichž existence je pouze kvůli podpoře Vytvoření jiných struktur kódu než těch, které jsou k dispozici v jazyce.

Zejména první hlavní bod výše je již povolen a druhý je vyčištěn (pokud goto z blok zásobníku je správně odvíjen a jsou volány všechny správné destruktory)

Tuto odpověď můžete odkázat na tuto odpověď , abyste získali představu o tom, jak sudý kód nefunguje používání goto může být nečitelné. Problém není sám, ale špatné použití.

Mohu napsat celý program bez použití if, stačí for. Samozřejmě to nebude dobře čitelné, vypadá to neohrabaně a zbytečně komplikovaně.

Problém však není for. To jsem já.

Věci jako break, continue, throw, bool needed=true; while(needed) {...} atd. si všímají více než maškarády goto k úniku před šavlemi djikstrarských fanatiků, že – 50 let po vynálezu moderních lagu – stále chtějí své vězně. Zapomněli, o čem Djikstra mluvil, pamatují si pouze název jeho poznámky (GOTO považováno za škodlivé a nebyl to ani jeho nový název: byl změněn editorem) a vinu a bash, bash a vinu za každou konstrukci, která má ty 4 písmeno umístěno v pořadí.

Je rok 2011: je čas pochopit, že goto se musí zabývat GOTO prohlášení, o kterém Djikstra byl přesvědčivý.

Komentáře

  • “ Věci jako zlomit, pokračovat , hod, bool potřeba = true; while (needed) {…}, etc. are noting more than maškaráda goto “ Nesouhlasím s tím ‚. Upřednostňuji “ věci jako break atd. Jsou omezené goto “ nebo něco podobného. Hlavním problémem goto je, že je obvykle příliš silný. Do té míry, že aktuální goto je méně silný než Dijkstra ‚ s, je vaše odpověď se mnou v pořádku.
  • @MuhammadAlkarouri: naprosto souhlasím. Právě jste našli lepší formulaci, která by vyjadřovala přesně můj koncept. Chci říct, že tato omezení někdy nemusí být použitelná a druh omezení, které potřebujete, není v jazyce. Díky tomu je řešení “ výkonnější “ méně specializované. Například Java break n není k dispozici v C ++, proto goto escape, i když escape není nutné, aby byl právě mimo smyčku n-ple.

Odpověď

Zvláštní goto zde nebo tam, pokud je pro funkci místní, jen zřídka významně poškozuje čitelnost. Často jí prospívá tím, že upozorňuje na skutečnost, že se v tomto kódu děje něco neobvyklého, což vyžaduje použití poněkud neobvyklé řídicí struktury .

Pokud (místní) gotos výrazně poškozují čitelnost, pak je to obvykle známka toho, že funkce obsahující goto se stala příliš složitou.

Poslední goto, které jsem vložil do Součástí kódu C bylo vytvoření dvojice vzájemně propojených smyček. Nevyhovuje normální definici „přijatelného“ použití goto, ale ve výsledku byla funkce podstatně menší a jasnější. Abychom se vyhnuli přechodu, vyžadovalo by to obzvláště chaotické narušení DRY.

Komentáře

  • Odpověď na to je nejpřesněji uvedena ve starém “ Lay ‚ s bramborové lupínky “ slogan: “ Vsadím se, že ‚ nemůžete jíst jen jednu „. Ve vašem příkladu máte dvě “ vzájemně propojené “ (ať už to znamená cokoli, a já ‚ m to není ‚ t pretty) smyček a goto vám dalo levnou nabídku. A co údržbář, který musí ten kód upravit, když vás srazil autobus? Udělá mu goto život jednodušší nebo těžší? Je potřeba tyto dvě smyčky přehodnotit?

Odpovědět

Myslím, že celý tento problém byl případem štěkání špatný strom.

GOTO jako takové mi nepřipadá problematické, ale spíše je to často příznak skutečného hříchu: špagetový kód.

Pokud GOTO způsobí hlavní křížení linek řízení toku, pak je to špatné období. Pokud nepřekročí žádné linie řízení toku, je to neškodné. V šedé zóně mezi tím máme věci jako záchranné smyčky, stále existují některé jazyky, které nepřidaly konstrukty, které pokrývají všechny legitně šedé případy.

Jediný případ, kdy jsem zjistil, že ho skutečně používám v mnoha letech je případ smyčky, kde je rozhodovací bod uprostřed smyčky. Zůstane vám buď duplikovaný kód, vlajka nebo GOTO. GOTO řešení považuji za nejlepší ze tří. Neexistuje zde žádné překročení řádků řízení toku, je to neškodné.

Komentáře

  • Případ, o kterém se zmiňujete, se někdy nazývá „smyčka a půl“ nebo „N plus jedna půl smyčka“ a jedná se o slavný případ použití pro goto s, které skočí do smyčky (pokud to jazyk umožňuje; protože druhý případ, skákání ze smyčky uprostřed, je obvykle triviální bez goto ).
  • (Bohužel, většina jazyků zakazuje skákat do smyčky.)
  • @KonradRudolph: Pokud implementujete “ smyčku “ s GOTO neexistuje žádná další struktura smyčky, do které by bylo možné skočit.
  • Přemýšlím o goto, jak křičí ŘÍDÍCÍ TOK ZDE NENÍ ‚ T FIT NORMÁLNÍ STRUKTUROVANÉ PROGRAMOVÁNÍ VZORY . Protože řídicí toky, které odpovídají strukturovaným vzorcům programování, jsou snadněji odůvodnitelné než ty, které nejsou ‚ t, měl by se pokusit použít tyto vzory, pokud je to možné; pokud kód těmto vzorům vyhovuje, nemělo by ‚ t křičet, že to ‚ t. Na druhou stranu, v případech, kdy kód opravdu

nevyhovuje takovým vzorům, může být lepší křičet, než předstírat, že se kód hodí, když to opravdu není ‚ t.

  • @supercat Představte si, že jste si napsali rozpis a pak vám to vítr vyfoukne z rukou. Podle vaší logiky byste jej neměli ‚ t načíst, protože pronásledování vašeho plánu nebylo ‚ t podle vašeho plánu.
  • Odpověď

    Ano, goto lze využít ve prospěch zkušeností vývojáře: http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

    Stejně jako u jiných výkonných nástrojů (ukazatele, vícenásobné dědičnosti atd.) je ale třeba být disciplinovaný používat to. Příklad uvedený v odkazu používá PHP, které omezuje použití konstrukce goto na stejnou funkci / metodu a zakazuje schopnost přeskočit do nového řídicího bloku (např. Smyčka, příkaz switch atd.)

    Odpověď

    Závisí na jazyce. Například je stále široce používán v programování Cobol. Pracoval jsem také na zařízení Barionet 50, jehož programovací jazyk firmwaru je raný základní dialekt, který samozřejmě vyžaduje použití Goto.

    Odpověď

    goto může být užitečná při přenosu staršího kódu assembleru do C. V prvním případě instrukce- konverze podle instrukcí na C pomocí goto jako náhrady za instrukci branch assembleru umožňuje velmi rychlé přenesení.

    Komentáře

    • Správně, ale jedním z argumentů proti goto s je, že maří optimalizaci kompilátoru.
    • @Sapphire_Brick: Mnoho optimalizací kompilátorů je navrženo podle určitých vzorů provádění. Pokud prováděný úkol neodpovídá podporovaným vzorům provádění ‚, “ maření “ optimalizace nemusí být špatná věc.

    Odpověď

    Tvrdil bych, že ne. Měli by být vždy nahrazeny nástrojem konkrétnějším pro problém, který se používá k řešení goto (pokud není k dispozici ve vašem jazyce). Například příkazy break a výjimky řeší dříve řešené problémy úniku smyčky a zpracování chyb.

    Komentáře

    • I ‚ argumentuji, že když mají jazyky oba tyto funkce goto v těchto jazycích obvykle chybí.
    • Ale je tomu tak proto, že ‚ nepotřebujete je, nebo proto, že lidé si myslí, že je ‚ nepotřebují?
    • Vaše názory jsou bigotní. Existuje mnoho případů, kdy goto je nejblíže velmi problémové sémantice domény, cokoli jiného by bylo špinavým hackem.
    • @ SK-logic: Já ‚ nemyslíte si, že slovo “ bigotní “ znamená to, co si myslíte, že to znamená.
    • @Keith,

    netolerantně oddaný svým vlastním názorům a předsudkům “ – tomu je ‚ důsledně zde pozorujte, s touto loterií se zavázanýma očima. “ Měly by být vždy nahrazeny “ jsou fanatičtí ‚ s alespoň slova. Nic blízkého správnému a zdravému názoru, ale jen čistá fanatismus. Toto “ vždy “ nenechává žádný prostor pro alternativní názor, viz?

    Odpověď

    Řekl bych, že ne. Pokud zjistíte, že je nutné používat GOTO, vsadím se, že je nutné kód přepracovat.

    Komentáře

    • Možná, ale vy útočiště ‚ neposkytlo žádné odůvodnění
    • Dijkstra poskytl odůvodnění podrobně před desítkami let.
    • Jen Dogma. Žádné rezonance. Poznámka: Djikstra NENÍ JAKÉKOLI PLATNÝM ODPOVĚDÍM: šlo o odkaz na příkaz BASIC nebo FORTRAN GOTO z počátku ‚ 60. let. Nemají nic společného se skutečně anemickými (ve srovnání s mocí těch) dnešních robotů.
    • @EmilioGaravaglia No, část jeho uvažování, která platí dodnes, spočívá v tom, že je ‚ velmi snadné psát špagetový kód pomocí cesty k mnoha gotům. Podle této logiky bychom však neměli ‚ používat ukazatele, protože použití tolik ukazatelů jako number of gotos needed to create problems by vytvořilo podobný chaos.

    Napsat komentář

    Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *