Goto

**GoTo** je kontrolna struktura, odnosno *direktiva*, *naredba*, "komanda" (engl. *statement*) koja postoji u mnogim programskim jezicima. Izvršava jednosmjerni prenos *kontrole toka* (*programski skok*) do odredjene lokacije u *izvornom kôdu* programa. Lokacija se uglavnom identificira imenovanom *labelom*, ili *rednim brojem* linije. U današnje vrijeme ova naredba se u programiranju uglavnom izbjegava, te postoji kritički odnos prema uporebi ove naredbe u strukturiranim programskim jezicima.

## Naziv

Programski jezici koji imaju `goto`, na različite načine i s različitim kombinacijama velikih i malih slova (*kapitalizacija*) su imenovali ovu direktivu, npr:

* `GOTO` (samo kapitalna slova) - FORTRAN, BASIC;

* `GO TO` (kapitalno, razdvojene riječi) - Neke stare verzije Basica u *Time-sharing* sistemima;

* `goto` (samo verzalna slova) - C, C++, C#;

* `goto`, `Goto`, `GoTo` ... (nebitna kapitalizacija) - Pascal i drugi programski jezici koji ne razlučuju kapitalizaciju *identifikatora* i *rezerviranih riječi* (engl. *keyword*).

## Upotreba

Sintaksa `goto` kontrolne strukture u svim jezicima je uglavnom ista:

`'''goto''' <Destination>`

gdje *destinacija* može biti označena linijskim brojem (*BASIC*, *FORTRAN 77*) ili *labelom*, posebnom imenovanom "konstantom" (*Pascal*, *C/C++*). Direktiva `goto` se obično upotrebljava unutar If-Then-Else blokova, na sledeći način:


```pascal
if <Expression> then
  goto <LabelName1>
else
  goto <LabelName2>
```


Programski jezik Pascal zahtijeva deklaraciju *labele*, kao i bilo koje druge *varijable*, *konstante* ili *tipa* podataka, dok se destinacija obilježava imenom labele iza koje slijedi dvotočka:


```pascal
label
  DstX;

goto DstX;

{ ... }

DstX:
  { ... }
```


Upotreba naredbe `goto` naročito je bila česta u starijim programskim jezicima sekvencijalnoga karaktera, umjesto pozivanja *podprograma* (*funkcija* ili *procedura*), kako se to inače radi u proceduralnim i funkcijskim jezicima. Za razliku od poziva funkcije, koji vraća kontrolu toka programa natrag nakon izvršenja, naredba `goto` prenosi kontrolu toka samo u jednom smjeru. Zbog toga nije pogodna za strukturirano programiranje i pisanje pregledna, uredna programskoga koda, što je dovelo do kritika protiv upotrebe naredbe još 60-ih godina 20. stoljeća.

Neki programski jezici ne podržavaju ovu naredbu, kao npr. Java, iako je u Javi `goto` *rezervirana riječ* (engl. *keyword*), što znači da se ne može koristiti za imenovanje identifikatora. Proceduralni programski jezici *Pascal* i *C/C++* podržavaju `goto`, ali ne dopuštaju skakanje izvan dosega funkcije ili procedure. PHP nije imao `goto` sve do verzije 5.3.

## Primjeri

### Pascal


```pascal
{$id: ALGMD-20100530}
unit Harmful;

interface(*********************************************************************)

function ProdOfInts(Op1, Op2: LongInt): LongInt;
function PowerOfInt(Base: LongInt; Exp: LongInt): LongInt;

implementation(****************************************************************)

var
  Result: LongInt;

function ProdOfInts(Op1, Op2: LongInt): LongInt;
label
  0, 1;
begin
0:
  Result := 0;
1:
  Result := Result + Op1;
  Op2 := Op2 - 1;

  if Op2 <> 0 then
    goto 1
  else if Op2 = 0 then
    ProdOfInts := Result;
end;

function PowerOfInt(Base: LongInt; Exp: LongInt): LongInt;
begin
  Result := 1;

  while Exp <> 0 do
  begin
    Exp := Exp - 1;
    Result := ProdOfInts(Base, Result);
  end;

  PowerOfInt := Result;
end;

begin(********************************************************************)end.
```


### Windows CMD


```dos
@echo off

setlocal
set project=Harmful
set options=-Sg -WN -Xs -XX

call :main
endlocal
goto :eof

:main
fpc %project%.pp %options%

if exist %project%.pp* (
	goto :eof
) else (
	call :error
)

goto :eof

:error
echo:
echo Compilation error.
pause

:eof
```


## Varijacije

### Razgranati Goto

Osim jednostavne *direktive* `goto`, još u starijim, nestrukturiranim verzijama *Fortrana* i *Basica* postojala je i složenija kontrolna struktura - **izračunati goto** ili **razgranati goto**. Za razliku od obične `goto` *instrukcije*, *razgranati goto* omogućuje više od jedne *destinacije* za *programski skok*, u ovisnosti o vrijednosti kondicionalne varijable ili *izraza* (*ekspresije*) unutar razgranate strukture. U Fortranu sintaksa izgleda ovako:

`'''goto''' (l1, l2, ... ln) <expr>`

Na primjer:


```fortran
GOTO (20, 30, 40) i
```


U ovom primjeru programski skok će se izvršiti na osnovi vrijednosti *cjelobrojne* (*integer*) varijable `i`. Za svako `i = n`, `GOTO` skače do one *destinacije* u listi (navedene u zagradi), za koju vrijedi da je njezin redni broj u listi jednak vrijednosti varijable `i`. Dakle:

 ? (i = 1) -> goto 20
 ? (i = 2) -> goto 30
 ? (i = 3) -> goto 40

Za bilo koju drugu vrijednost `i` različitu od `1, 2, 3`, ne će se izvršiti nijedan od skokova.

Basic je imao sličnu razgranatu strukturu s istom funkcionalnošću, `ON ... GOTO`, odnosno `GO TO ... OF ...` (u ovisnosti o verziji Basica). Primjer upotrebe:


```thinbasic
50 ON i GOTO 100, 200, 300, 400
```


Starija, manje poznata varijanta:


```thinbasic
50 GO TO N OF 100, 200, 300, 400
```


U modernijim, strukturiranim programskim jezicima, umjesto ove razgranate strukture koristi se različito nazvana *instrukcija višestrukoga izbora*: `switch` (*C/C++*), `case` (*Pascal*), `select case` (*Fortran 90*, *QBasic*, *Visual Basic*).

## Slične naredbe

### GoSub

`GOSUB` ili `GO SUB` je naredba u Basicu za pozivanje **podprograma**. Za razliku od `GOTO` naredbe u Basicu, koja vrši jednosmjeran transfer kontole toka, `GOSUB` omogućuje povratak na mjesto pozivanja, nakon izvršenja podprograma, pomoću ključne riječi `RETURN`.

`'''GOSUB''' <expr> <...> '''RETURN'''`

Kako je `GOSUB ... RETURN` konstrukcija u Basicu riješena na posve nestrukturiran način, iza koda glavnoga programa i prije početka pisanja podprograma mora se navesti ključna riječ `STOP`, da bi se osiguralo da program nakon izvršenja glavnoga dijela ne nastavi izvršavanje svih navedenih podprograma onim redom kojim su upisani.

Primjer:


```thinbasic
10 REM *** Rješavanje kvadratne jednačbe ***
20 PRINT "Koliki su koeficijenti a, b, c? "
30 INPUT A, B, C
40 GOSUB 500
45 IF (B^2 - 4*A*C) < 0 THEN 10
50 PRINT "Korijeni ove jednačbe su: "
60 PRINT "x1 = "; X1 "x2 = "; X2
70 STOP
500 REM *** Podprogram za determinantu ***
510 IF (B^2 - 4*A*C) < 0 THEN 600
520 X1 = (-B + (B^2 - 4*A*C)^(1/2)) / (2*A)
530 X2 = (-B + (B^2 - 4*A*C)^(1/2)) / (2*A)
540 GOTO 610
600 PRINT "Determinanta je manja od nule. "
610 RETURN
620 END
```


### On ... GoSub

Slično kao razgranati `GOTO`, i `GOSUB` ima svoju razgranatu varijantu.
`GOSUB` instrukcija koja odlučuje o programskom skoku na osnovi evaluacije izraza, ima sledeći oblik:

`'''ON''' <expr> '''GOSUB''' <d1, d2, d3, ... dn>`

Manje popularna varijanta u nekim starijim *BASIC* interpreterima / *Time-sharing* sistemima:

`'''GO SUB''' <expr> '''OF''' <d1, d2, d3, ... dn>`

Npr:

```thinbasic
50 GOSUB X OF 110, 210, 320, 1400
```


Izvršenje:

 x = 1 : GOTO 110;
 x = 2 : GOTO 210;
 x = 3 : GOTO 320;
 x = 4 : GOTO 1400;
 x  4 : GOSUB se ne izvršava, jer su zadane samo 4 destinacije;

### Break & Continue

U programskom jeziku C, osim `goto` postoje i naredbe za skok iz petlje. Naredba `break` prekida izvršavanje petlje unutar koje je pozvana vraćajući tok programa na lokaciju prije pojavljivanja petlje, dok `continue` ponovno testira brojač (ako je u pitanju `for` iteracija) ili uslov iteracije (kod `while` petlji). Primjeri korištenja `break` i `continue` skokova preuzeti su iz knjige *Programski jezik C* autora Dennisa Ritchieja i Briana Kernighana.

* **Break**


```c
/* trim: remove trailing blanks, tabs, newlines */
int trim(char s[])
{
	int n;

	for (n = strlen(s)-1; n >= 0; n--)
		if (s[n] != ' ' && s[n] != '\t' && s[n] != '\n')
			break;

	s[n+1] = '\0';
	return n;
}
```


* **Continue**


```c
for (i = 0; i < n; i++)
	if (a[i] < 0) /* skip negative elements */
		continue;

	/* do positive elements */
```


## Izvori