PHP para Iniciantes: Estruturas de Controle - GOTO

A imagem a seguir é a introdução atual do artigo na documentação oficial do PHP, uma cortesia do xkcd.

GOTO

Traduções para quem não manja do inglês:

  • Q. 1: Eu poderia reestruturar o fluxo do programa - ou usar um pequeno 'GOTO' ao invés disso.
  • Q.2 : Ah, dane-se as boas práticas. Quão errado pode ser isso? goto main_sub3; ... *compila*

E aí acontece a invocação do dinossauro de dentro deste ser.

Bem, isso por conta própria já reflete a opinião (quase) unânime sobre o uso dessa estrutura de controle. Se você planeja aprender para usar, é melhor nem ler o resto do artigo, rs.

Ué, Kiko, por que você está escrevendo então?

Assim como eu precisei escrever sobre o operador de controle de erro (@), eu também preciso escrever sobre goto. É aquele tipo de coisa que você precisa aprender para evitar utilizar e saber como desfazer caso encontre um projeto usando, sabe?

Enfim, apesar de todo esse terror psicológico, goto na verdade é uma das estruturas mais simples que existe, porque ele ordena exatamente o que propõe: VÁ PARA (referênciaDoLugar). O que pode ser não tão claro assim é sobre como construir uma referência, de fato.

É um nome? Uma linha? Um arquivo? A casa do Car-los?

Essa referência é um nome que funciona como um ponteiro, você precisará criar uma identificação para uma seção e esse nome vai funcionar como a porta de entrada para a chamada do goto.

O nome não precisa existir na interpretação antes da chamada dessa estrutura, mas precisa estar no mesmo escopo. Sendo assim, você não pode fazer um salto entre funções, nem de dentro para fora nem de fora para dentro, pois são escopos diferentes.

Apesar de você não conseguir saltar para dentro de um laço de repetição (loop) ou de um switch, você consegue acionar o goto de dentro dessas estruturas, funcionando como um break, pois o escopo de fora delas ainda é o mesmo escopo. Mesmo assim, você só pode saltar para áreas identificadas no mesmo escopo, não fora.

Ah, Kiko, mostra como raios funciona isso logo...

Ok!

Exemplo 1: casa do Carlos

<?php

goto casaDoCarlos;
echo 'Eu não sou cachorro não' . PHP_EOL;



casaDoCarlos:
echo 'De bar em bar, de mesa em mesa...';

O resultado disso será

De bar em bar, de mesa em mesa...

E o que ocorre é bem simples: o interpretador vê o comando goto, verifica se já interpretou alguma identificação para saltar, o que não ocorreu, então passa a buscar uma instrução que indique o nome casaDoCarlos. Ao encontrar, salta para aquele ponto e volta a interpretar.

O que significa, que se fosse ao contrário, também funcionaria... Mas é preciso tomar cuidado com loops infinitos. Para o exemplo abaixo, vou colocar um contador que ao ser contado duas vezes, irá encerrar o código para evitar isso.

Exemplo 2: de volta para o futuro

<?php

$ano = 2021;
$contador = 0; // antes do loop né?
futuro:
echo "Estamos em $ano!" . PHP_EOL;

if(++$contador < 2) {
    $ano = 2077;
    goto futuro;
}
echo 'O_O';

E o resultado desse é:

Estamos em 2021!
Estamos em 2077!
O_O

Ou seja, é possível demarcar uma zona de retorno para saltar com o goto. Sim, é possível fazer loops com goto. Também é possível encerrar os loops com ele...

Exemplo 3: o falso break

<?php // PHP 8

$valido = fn() => false; // imagine que isso aqui é uma função que retorna true/false

for ($algumaCoisa = 0; $algumaCoisa < 1000; $algumaCoisa++) {
    if (!$valido()) {
        goto end; // break?
    }
    echo $algumaCoisa . PHP_EOL;
}

end:
echo 'É o fim, e ele nem tinha começado...';

Resulta em:

É o fim, e ele nem tinha começado...

Detalhes...

Tem uma parada que preciso mencionar: esses nomes não podem ser expressões nem tipos de dados primitivos. Colocar uma string não funciona, tampouco uma variável. Se escrever uma constante, ele vai pegar a escrita, não o valor da constante:

<?php

define('END', 'É O FIMMMMMMMM');

goto END;

END: // o goto vai saltar para cá, naturalmente, o ponto END
echo END; // e aqui vai usar o valor da constante

Kiko, parece bem prático...

NÃO, NÃO É PRÁTICO. Isso é uma ILUSÃO. Você até pode resolver uma urgência com isso mas certamente precisará refatorar o código depois, pois fica bizarro, beleza? Você pode pesquisar por exemplos na web e se você acompanha as boas práticas de desenvolvimento, você vai entender porque, apesar de parecer legal e prático, não é.

E por hoje é só! Curtiu?! Comenta e compartilha!! Esse foi o último artigo sobre estruturas de controle, o que indica que tem mais uma introdução vindo por aí... A partir do próximo, falaremos sobre FUNÇÕES (aaaaaleluia, aaaaaaaleluia). Como de costume, vou dar uma visão geral sobre o assunto com micro spoilers pra você pegar a ideia básica e só depois vou me aprofundar em cada trecho dessa seção maravilhosa, beleza??!

Inté!!