5.8 KiB
5.8 KiB
GOTO Keyword
⚠️ WARNING: GOTO is supported but NOT RECOMMENDED
While GOTO works for backward compatibility, you should use event-driven patterns with the ON keyword instead. GOTO makes code harder to maintain and debug.
Syntax
label:
' statements
GOTO label
IF condition THEN GOTO label
Description
GOTO transfers program execution to a labeled line. Labels are identifiers followed by a colon (:) at the start of a line.
This keyword exists for backward compatibility only. Modern General Bots code should use:
ON INSERT/UPDATE/DELETE OFfor event-driven programmingWHILE ... WENDfor loopsFOR EACH ... NEXTfor iterationSUB/FUNCTIONfor code organization
❌ OLD WAY vs ✅ NEW WAY
Polling Loop (Don't Do This)
' ❌ BAD: GOTO-based polling loop
mainLoop:
leads = FIND "leads", "processed = false"
FOR EACH lead IN leads
CALL processLead(lead)
NEXT lead
WAIT 5
GOTO mainLoop
Event-Driven (Do This Instead)
' ✅ GOOD: Event-driven with ON keyword
ON INSERT OF "leads"
lead = GET LAST "leads"
score = SCORE LEAD lead
IF score.status = "hot" THEN
TALK TO "whatsapp:" + sales_phone, "🔥 Hot lead: " + lead.name
END IF
END ON
Why ON is Better Than GOTO
| Aspect | GOTO Loop | ON Event |
|---|---|---|
| Efficiency | Polls constantly, wastes CPU | Triggers only when data changes |
| Code clarity | Spaghetti code, hard to follow | Clear cause-and-effect |
| Resource usage | Always running | Idle until triggered |
| Scalability | Degrades with more data | Handles scale naturally |
| Debugging | Hard to trace execution | Clear event flow |
| LLM integration | Poor | Works well with TOOLs |
If You Must Use GOTO
For legacy code migration or specific use cases, GOTO is supported:
Simple Loop
counter:
TALK "Count: " + x
x = x + 1
IF x < 5 THEN GOTO counter
TALK "Done!"
Multiple Labels
start:
TALK "Starting..."
GOTO process
error:
TALK "An error occurred"
GOTO cleanup
process:
result = DO_SOMETHING
IF result = "error" THEN GOTO error
TALK "Success!"
GOTO cleanup
cleanup:
TALK "Cleaning up..."
Conditional GOTO
check:
IF temperature > 30 THEN GOTO too_hot
IF temperature < 10 THEN GOTO too_cold
TALK "Temperature is comfortable"
GOTO done
too_hot:
TALK "Warning: Too hot!"
GPIO SET fan_pin, HIGH
GOTO done
too_cold:
TALK "Warning: Too cold!"
GPIO SET heater_pin, HIGH
GOTO done
done:
TALK "Check complete"
How GOTO Works Internally
GOTO is not native to the Rhai engine. General Bots transforms GOTO-based code into a state machine:
' Your code:
loop:
x = x + 1
IF x < 3 THEN GOTO loop
TALK "Done"
' Transformed internally to:
let __goto_label = "loop"
while __goto_label != "__exit" {
if __goto_label == "loop" {
x = x + 1
if x < 3 { __goto_label = "loop"; continue; }
TALK "Done"
__goto_label = "__exit"
}
}
This transformation:
- Adds overhead compared to native loops
- Has a safety limit of 1,000,000 iterations to prevent infinite loops
- Emits warnings in the server logs recommending ON patterns
Limitations
| Limitation | Description |
|---|---|
| No computed GOTO | GOTO variable is not supported |
| No GOSUB | Use SUB / CALL instead |
| No line numbers | Only named labels are supported |
| Performance | Slower than native WHILE loops |
| Iteration limit | Maximum 1,000,000 iterations per GOTO loop |
Migration Guide
From GOTO Loop to WHILE
' Before (GOTO):
start:
TALK "Hello"
x = x + 1
IF x < 10 THEN GOTO start
' After (WHILE):
WHILE x < 10
TALK "Hello"
x = x + 1
WEND
From GOTO Loop to ON Event
' Before (GOTO polling):
checkOrders:
orders = FIND "orders", "status = 'new'"
FOR EACH order IN orders
CALL processOrder(order)
NEXT order
WAIT 10
GOTO checkOrders
' After (ON event):
ON INSERT OF "orders"
order = GET LAST "orders"
IF order.status = "new" THEN
CALL processOrder(order)
END IF
END ON
From GOTO Error Handling to ON ERROR
' Before (GOTO):
result = RISKY_OPERATION
IF result = "error" THEN GOTO handleError
TALK "Success"
GOTO done
handleError:
TALK "Failed!"
done:
' After (ON ERROR):
ON ERROR RESUME NEXT
result = RISKY_OPERATION
IF ERROR THEN
TALK "Failed!"
ELSE
TALK "Success"
END IF
ON ERROR GOTO 0
Best Practices
- Don't use GOTO for new code - Use WHILE, FOR EACH, ON, or SUB/FUNCTION
- Migrate existing GOTO code - Refactor to event-driven patterns when possible
- If you must use GOTO - Keep it simple, avoid deep nesting
- Add comments - Explain why GOTO is necessary
- Set reasonable limits - Don't rely on the 1M iteration safety limit
See Also
- ON Keyword - Recommended: Event-driven programming
- WHILE ... WEND - Loop construct
- FOR EACH ... NEXT - Iteration
- SUB / FUNCTION - Code organization
- ON ERROR - Error handling
Summary
| Use Case | Instead of GOTO, Use |
|---|---|
| Polling for changes | ON INSERT/UPDATE/DELETE OF |
| Repeating code | WHILE ... WEND |
| Iterating collections | FOR EACH ... NEXT |
| Reusable code blocks | SUB / FUNCTION + CALL |
| Error handling | ON ERROR RESUME NEXT |
| Conditional branching | IF ... ELSEIF ... ELSE ... END IF |
| Multiple conditions | SWITCH ... CASE ... END SWITCH |
The ON keyword is the future. GOTO is the past.