Goto to instrukcja występująca w wielu językach programowania. Nazwa pochodzi od angielskich słów go i to i oznacza bezwarunkowy skok do innej etykiety (linii) w kodzie. Innymi słowy, instrukcja pozwala przenieść wykonywanie programu w miejsce oznaczone etykietą.

Krótka charakterystyka

Wiele języków wspiera instrukcję goto, a wiele nie. W Javie słowo goto jest zarezerwowane, ale nie można go używać w kodzie źródłowym. (Słowo zarezerwowane to słowo będące częścią składni języka, którego nie można użyć np. jako nazwy zmiennej, funkcji czy klasy — por. zmiennych.)

Składnia i przykłady

Dokładna składnia zależy od języka, ale schemat jest prosty: definiuje się etykietę, do której można skoczyć, a następnie używa się instrukcji goto, aby przekierować wykonanie programu do tej etykiety. Przykład w stylu C:

goto koniec; /* ... inne instrukcje ... */ koniec: /* kod po skoku */ 

W praktyce często używa się analogicznych konstrukcji w językach niskiego poziomu (assembler), w starych dialektach BASIC‑a, w C/C++ (gdzie goto istnieje), a także w PHP, Perl czy Fortranie. W nowocześniejszych językach (np. Python, Ruby) instrukcja goto zwykle nie występuje albo jest świadomie pomijana.

Przykładowe zastosowania

  • Obsługa błędów i sprzątanie zasobów: w kodzie C, zamiast powtarzać zwalnianie zasobów w wielu miejscach, często stosuje się etykietę końcową, do której skacze się z różnych miejsc przy błędzie, aby scentralizować cleanup.
  • Wyjście z wielu zagnieżdżonych pętli: gdy brak jest wygodnego mechanizmu przerywania kilku poziomów pętli, goto bywa użyteczne.
  • Kod generowany automatycznie i maszyny stanów: niektóre generatory kodu lub translatory używają skoków dla czytelności generowanego kodu maszynowego.
  • Optymalizacje niskiego poziomu: w wyjątkowych sytuacjach, tam gdzie liczy się każdy cykl procesora, programista może użyć goto do uzyskania prostszej ścieżki wykonania.

Twierdzenie o programach strukturalnych i krytyka

W informatyce istnieje teoria znana jako twierdzenie o programach strukturalnych (Böhm–Jacopini). Twierdzenie to mówi, że każdy program można zapisać wyłącznie przy użyciu struktur takich jak sekwencja instrukcji, warunki (if/then/else) i pętle, bez użycia instrukcji goto. Innymi słowy, formalnie goto nie jest konieczne do realizacji dowolnego algorytmu.

Mimo to kontrowersje wokół goto są długie i głębokie. Najsłynniejsza krytyka pochodzi od Edsgera Dijkstry (esej "Go To Statement Considered Harmful"), który argumentował, że nadmierne użycie skoków pogarsza czytelność i utrudnia utrzymanie kodu. Główne zarzuty to:

  • spadek przejrzystości przepływu programu,
  • trudności w analizie i testowaniu,
  • większe ryzyko błędów (np. niejawne pominięcia inicjalizacji),
  • utrudnione refaktoryzacje i współpracę w zespole.

Ograniczenia twierdzenia i praktyczny punkt widzenia

Warto podkreślić, że choć twierdzenie Böhm–Jacopini dowodzi możliwości zastąpienia goto konstrukcjami strukturalnymi, to w praktyce zamiana czasami wymaga dodania dodatkowych zmiennych sterujących lub bardziej złożonych konstrukcji, co może pogorszyć czytelność lub wydajność. Dlatego decyzja o użyciu goto powinna być rozważna i uzasadniona konkretnymi korzyściami.

Alternatywy i dobre praktyki

  • Stosuj funkcje/metody (funkcji, metod) do wydzielania logicznych fragmentów kodu zamiast wielu skoków.
  • Używaj strukturalnych pętli i instrukcji warunkowych, wyjątków (tam, gdzie są dostępne) oraz mechanizmów takich jak break/continue czy oznakowane przerwania (labeled break) — to często czytelniejsze rozwiązania.
  • Jeśli już używasz goto, ogranicz jego zasięg do małych fragmentów funkcji, stosuj przejrzyste nazwy etykiet i dodaj komentarz wyjaśniający powód użycia.
  • Preferuj centralne mechanizmy sprzątania zasobów (np. RAII w C++, finally w językach obsługujących wyjątki), zamiast szerokich skoków do etykiety cleanup.

Podsumowanie

Instrukcja goto to potężne, ale kontrowersyjne narzędzie. Teoretycznie nie jest potrzebna do budowy poprawnych programów (zgodnie z twierdzeniem o programach strukturalnych), ale w praktyce znajduje zastosowanie w specyficznych sytuacjach (sprzątanie, kod generowany, niskopoziomowe optymalizacje). Z punktu widzenia dobrego projektowania kodu zaleca się ostrożność: preferować strukturalne konstrukcje i czytelność, a goto stosować tylko wtedy, gdy przynosi wyraźne korzyści.