Uso de la declaración goto

GolangGolangBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En comparación con las declaraciones de bifurcación y bucle, la declaración goto es más flexible. Nos permite realizar saltos incondicionales dentro de la misma función. Si bien el uso excesivo de goto puede reducir la legibilidad del código, su principal ventaja radica en su flexibilidad. Cuando se utiliza adecuadamente, no solo mejora la eficiencia del programa, sino que también hace que el código sea más conciso y elegante en ciertos escenarios.

En este laboratorio (lab), aprenderás los conceptos básicos de cómo usar la declaración goto en Go, junto con su aplicación en diferentes escenarios, como reemplazar declaraciones break, implementar bucles y salir de bucles anidados.

Puntos de conocimiento:

  • Sintaxis y uso de goto
  • Aplicaciones prácticas de goto en programas de Go

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/FunctionsandControlFlowGroup(["Functions and Control Flow"]) go/FunctionsandControlFlowGroup -.-> go/for("For") go/FunctionsandControlFlowGroup -.-> go/functions("Functions") subgraph Lab Skills go/for -.-> lab-149074{{"Uso de la declaración goto"}} go/functions -.-> lab-149074{{"Uso de la declaración goto"}} end

Comprendiendo la sintaxis de goto

La sintaxis de goto es la siguiente:

// Syntax 1: Jumping forward
goto label
...
label: code block

// Syntax 2: Jumping backward
label: code block
goto label

En Go, goto ofrece flexibilidad ya que puede saltar hacia adelante y hacia atrás en el código. La etiqueta (label) es esencialmente un marcador que identifica a dónde debe saltar el control del programa. Las etiquetas distinguen entre mayúsculas y minúsculas, y se recomienda usar letras mayúsculas para las etiquetas para mejorar la legibilidad.

Nota: Tanto la declaración como el uso de las etiquetas deben ocurrir dentro de la misma función.

Ejemplo: Un programa simple con goto

Exploremos un programa simple que demuestra el uso de goto. En este ejemplo, el programa omite ciertas líneas y salta directamente a la etiqueta:

  1. Crea un nuevo archivo Go llamado goto.go ejecutando los siguientes comandos:
cd ~/project
touch goto.go
  1. Abre el archivo y escribe el siguiente código:
package main

import "fmt"

func main() {
    fmt.Println(1)  // Prints the number 1
    goto NEXT        // Jumps to the label "NEXT"
    fmt.Println(2)  // This line is skipped
NEXT:
    fmt.Println(3)  // Prints the number 3
}
  • El programa comienza imprimiendo el número 1.
  • Luego encuentra la declaración goto NEXT, que hace que se salte inmediatamente a la etiqueta NEXT.
  • Como resultado, la línea fmt.Println(2) se omite, y el programa reanuda la ejecución desde la etiqueta NEXT, imprimiendo el número 3.
  1. Ejecuta el programa:
go run goto.go
  1. Observa la salida:
1
3

Este sencillo ejemplo muestra cómo se puede usar goto para controlar el flujo del programa de manera directa.

Reemplazando break con goto

En ciertas situaciones, goto se puede utilizar como sustituto de la declaración break en bucles, brindando flexibilidad para salir de los bucles basado en condiciones específicas.

Ejemplo: Usando goto para salir de un bucle

  1. Crea un nuevo archivo Go llamado break_with_goto.go:
cd ~/project
touch break_with_goto.go
  1. Escribe el siguiente código en el archivo:
package main

import "fmt"

func main() {
    for i := 0; ; i++ {         // An infinite loop
        if i == 10 {            // Condition to exit the loop
            goto END            // Jump to the "END" label
        }
        fmt.Print(i)            // Print the current value of i
    }
END:
    fmt.Println("END")          // Print "END" after exiting the loop
}
  • El programa inicia un bucle infinito con for i := 0; ; i++.
  • Dentro del bucle, verifica si i es igual a 10. Si es verdadero, salta a la etiqueta END, saliendo efectivamente del bucle.
  • Antes de saltar, imprime los valores de i desde 0 hasta 9.
  • Después de salir del bucle, el programa imprime END.
  1. Ejecuta el programa:
go run break_with_goto.go
  1. Observa la salida:
0123456789END

Este ejemplo demuestra cómo goto puede reemplazar una declaración break en un bucle, ofreciendo una forma alternativa de terminar bucles.

Implementando un bucle for usando goto

goto también se puede utilizar para implementar manualmente un bucle. Si bien Go proporciona bucles for nativos, este ejercicio demuestra cómo goto puede emular el comportamiento de un bucle.

Ejemplo: Un bucle for con goto

  1. Crea un nuevo archivo llamado for_loop_with_goto.go:
cd ~/project
touch for_loop_with_goto.go
  1. Escribe el siguiente código:
package main

import "fmt"

func main() {
    var i = 0            // Initialize a variable i
BEGIN:
    fmt.Printf("%d ", i) // Print the current value of i
    if i == 9 {          // Check if i has reached 9
        goto END         // Exit the loop if true
    }
    i++                  // Increment i
    goto BEGIN           // Jump back to the label "BEGIN"
END:
}
  • El programa inicializa i en 0 y comienza el bucle utilizando la etiqueta BEGIN.
  • Imprime el valor de i y verifica si ha alcanzado 9.
  • Si no es así, incrementa i y salta de nuevo a la etiqueta BEGIN, repitiendo el proceso.
  • Una vez que i es igual a 9, el programa salta a la etiqueta END, terminando el bucle.
  1. Ejecuta el programa:
go run for_loop_with_goto.go
  1. Observa la salida:
0 1 2 3 4 5 6 7 8 9

Este ejemplo ilustra cómo goto puede imitar las estructuras de bucle.

Salir de bucles anidados con goto

Salir de bucles anidados puede ser engorroso utilizando break, ya que generalmente requiere lógica adicional y variables. goto simplifica este proceso al permitir saltos directos fuera de múltiples bucles.

Ejemplo: Usando goto para salir de bucles anidados

  1. Crea un nuevo archivo llamado nested_loop_with_goto.go:
cd ~/project
touch nested_loop_with_goto.go
  1. Escribe el siguiente código:
package main

import "fmt"

func main() {
    for i := 0; i < 5; i++ {      // Outer loop
        for j := 0; j < 5; j++ {  // Inner loop
            if j == 3 {           // Exit condition
                goto END          // Jump to the "END" label
            }
            fmt.Println(i, j)     // Print the current values of i and j
        }
    }
END:
}
  • El programa comienza con un bucle anidado: un bucle exterior para i y un bucle interior para j.
  • Dentro del bucle interior, verifica si j es igual a 3. Si es verdadero, el programa salta a la etiqueta END, saliendo de ambos bucles.
  • Como resultado, el programa imprime las parejas (i, j) solo hasta que j es igual a 2.
  1. Ejecuta el programa:
go run nested_loop_with_goto.go
  1. Observa la salida:
0 0
0 1
0 2

Este enfoque es mucho más limpio que usar múltiples declaraciones break o banderas (flags), especialmente en bucles profundamente anidados.

Si usamos la declaración break para implementar este programa, como se muestra a continuación:

package main

import "fmt"

func main() {
    // Check variable
    var check = false
    // First loop
    for i := 0; i < 5; i++ {
        // Second loop
        for j := 0; j < 5; j++ {
            if j == 3 {
                // Exit the second loop
                check = true
                break
            }
            fmt.Println(i, j)
        }
        // Determine whether to exit the first loop
        if check == true {
            break
        }
    }
}

Resumen

En este laboratorio (lab), exploramos la declaración goto en Go y sus diversas aplicaciones. Esto es lo que aprendimos:

  • La declaración goto permite saltos incondicionales a etiquetas (labels) especificadas dentro de la misma función.
  • Se puede utilizar para reemplazar declaraciones break, implementar bucles y salir de bucles anidados de manera más eficiente.
  • Si bien goto ofrece flexibilidad y concisión, se debe utilizar con moderación para evitar reducir la legibilidad del código.

Al entender y utilizar goto de manera efectiva, puedes simplificar ciertos escenarios de flujo de control en tus programas. Sin embargo, siempre busca la claridad y la mantenibilidad en tu código.