goto#
Transfer execution elsewhere in the program without returning.
goto has three unrelated forms that share only a keyword. The
useful one in modern Perl is goto &NAME — the tail-call form,
which replaces the current subroutine frame with a call to another
sub while preserving @_. The goto LABEL and goto EXPR forms
exist, are constrained, and are almost never the right tool.
Synopsis#
goto LABEL
goto EXPR
goto &NAME
What you get back#
goto does not return. Control leaves the goto statement and does
not come back. The return value of the construct the goto eventually
lands in is the value of the enclosing expression.
For goto &NAME, the return value is whatever the target subroutine
returns, propagated to the original caller as if the target had been
called directly.
The tail-call form: goto &NAME#
This is the form that matters. It exits the current subroutine —
undoing any local bindings — and immediately calls NAME with the
current @_. The current frame is replaced, not stacked on top
of.
Consequences:
callerinside the target sub sees the original caller, not the sub that issued thegoto. The intermediate frame is gone.@_is passed through as-is. Modifications to@_before thegotoare visible to the target.localchanges made in the departing sub are undone before the target runs, exactly as they would be on a normal return.The target does not have to know it was reached via
goto &; from its perspective it was called normally.
The canonical use is AUTOLOAD dispatch: resolve the real sub, then
goto it so stack traces, caller, and wantarray all behave as
though the real sub had been called in the first place.
NAME need not be a literal name. It can be any expression that
yields a code reference — a scalar holding a coderef, a block
returning one, or a dereferenced slot.
goto &$coderef;
goto &{ $dispatch{$op} };
For recursive tail calls, goto __SUB__ jumps to the currently
executing sub without re-resolving its name — safe under renaming
and anonymous subs.
The goto LABEL form#
Finds the statement labeled LABEL within the current dynamic scope
and resumes execution there. In practice this means it can jump out
of blocks and out of subroutines, but it cannot jump into a
construct that requires initialization — a subroutine body, a
foreach loop, a given block, the parameter of a binary or list
operator, or code the optimizer removed. Jumping into such a
construct is a fatal error as of Perl 5.44.
Most of what goto LABEL could do is better expressed with labeled
loop control (last LABEL, next LABEL, redo LABEL) or with
exceptions (die / eval). Reach for those first.
The goto EXPR form#
Evaluates EXPR. If it yields a code reference, behaves like
goto &NAME. If it yields a string, that string is used as a label
name resolved at runtime — a computed goto. The same restrictions as
goto LABEL apply to the label case.
Two parser quirks to remember:
goto EXPRis exempt from the “looks like a function” rule. Parentheses aftergotodo not necessarily delimit its argument:goto("NE")."XT"isgoto NEXT, notgoto "NE"followed by a useless concatenation.gotohas the same precedence as assignment, unlike most named operators.
Examples#
Tail-call dispatch from AUTOLOAD — the target sub sees the original
caller, not AUTOLOAD:
sub AUTOLOAD {
our $AUTOLOAD;
my ($method) = $AUTOLOAD =~ /::(\w+)\z/;
my $code = $self->can_really($method)
or die "no such method: $method";
goto &$code; # @_ forwarded, caller() unchanged
}
Tail recursion without growing the call stack. __SUB__ resolves to
the currently running sub:
sub fact {
my ($n, $acc) = @_;
$acc //= 1;
return $acc if $n <= 1;
@_ = ($n - 1, $acc * $n);
goto __SUB__;
}
Computed goto via goto EXPR. The label is chosen at runtime from
a list:
goto ("FOO", "BAR", "GLARCH")[$i];
FOO: handle_foo(); return;
BAR: handle_bar(); return;
GLARCH: handle_glarch(); return;
Delegating to a coderef held in a dispatch table. The caller never sees the intermediate frame:
my %ops = (
add => sub { $_[0] + $_[1] },
mul => sub { $_[0] * $_[1] },
);
sub run_op {
my $op = shift;
goto &{ $ops{$op} // die "unknown op: $op" };
}
Modifying @_ before a tail call — changes are visible to the target:
sub wrap {
unshift @_, "prefix";
goto &real_handler; # real_handler sees ("prefix", @orig_args)
}
Edge cases#
goto LABELcannot enter a sub,foreach, orgiven. As of Perl 5.44 this is a fatal error, not a warning. It also cannot jump into optimized-away code or into most operator operands — the one exception is the first operand of a binary operator (for=, the right-hand side).goto LABELcannot get out of asortcomparison block. The comparator runs in a context that does not permit the jump.goto &NAMEdiscardslocalbindings from the departing sub before the target runs. Anything the sub localized is restored as though the sub had returned normally.calleris invisible past agoto &. The departing frame is gone. This is the whole point of the form forAUTOLOAD— do not rely on seeing the intermediate sub in a stack trace.@_aliasing is preserved. The target sub’s@_aliases the same scalars the departing sub’s@_did. Assigning to$_[0]in the target still modifies the caller’s argument.goto &$coderefrequires a real coderef. A string that looks like a sub name does not work in the&form — usegoto EXPR(without the&) for that, or resolve the name to a coderef first with\&{$name}.gotohas assignment precedence.goto "A" . "B"isgoto "AB", not(goto "A") . "B".
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
last— exit the innermost or a named enclosing loop; the right tool for most “jump out of here” casesnext— skip to the next iteration of a loop, with optional labelredo— restart the current loop iteration without re-evaluating the conditionreturn— leave the current sub with a value; compare withgoto &NAMEwhich leaves the sub by replacing itcaller— inspect the call stack; note thatgoto &makes the departing frame invisible to it