One place for hosting & domains

      bucles

      Cómo crear bucles for en Go


      Introducción

      En el ámbito de la programación informática, un bucle es una estructura de código que forma un ciclo para ejecutar parte de un código de forma repetida, a menudo hasta que se cumple una condición. Usar bucles en el terreno de la programación informática le permite automatizar y repetir tareas similares varias veces. Imagine que tiene una lista de archivos que debe procesar, o que quiere contar el número de líneas de un artículo. Usaría un bucle en su código para resolver estos tipos de problemas.

      En Go, un bucle for implementa la ejecución repetida de código en base a un contador de bucles o una variable de bucle. A diferencia de otros lenguajes de programación que tienen varias construcciones en bucle como while y do, entre otras, Go solo tiene el bucle for. Esto sirve para hacer que su código sea más claro y legible, ya que no debe preocuparse por la presencia de varias estrategias para lograr la misma construcción en bucles. Esta mejora en la legibilidad y reducción de la carga cognitiva durante el desarrollo también harán que su código esté menos expuesto a errores que en otros lenguajes.

      A través de este tutorial, aprenderá sobre el funcionamiento del bucle for de Go y sobre las tres variaciones principales de su uso. Comenzaremos mostrando la forma de crear diferentes tipos de bucles for y luego veremos la forma de crear un bucle a través de tipos de datos secuenciales en Go. Para finalizar, explicaremos la forma de usar bucles anidados.

      Declarar bucles ForClause y Condition

      Para tener en cuenta varios casos de uso, existen tres formas distintas de crear bucles for en Go, cada una con sus propias capacidades. Implican crear un bucle for con una Condition, una ForClause o una RangeClause. En esta sección, explicaremos la forma de declarar y usar las variantes ForClause y Condition.

      Veamos la manera en que podemos usar primero un bucle for con la ForClause.

      Un bucle ForClause se define como un bucle que tiene una instrucción inicial seguida de una condición y luego una posinstrucción. Estas se organizan en la siguiente sintaxis:

      for [ Initial Statement ] ; [ Condition ] ; [ Post Statement ] {
          [Action]
      }
      

      Para explicar la función de los componentes anteriores, veremos un bucle for que se incrementa a través de un rango de valores especificados usando la sintaxis de ForClause:

      for i := 0; i < 5; i++ {
          fmt.Println(i)
      }
      

      Desglosaremos este bucle e indentificaremos cada parte.

      La primera parte del bucle es i := 0. Esta es la instrucción inicial.

      for i := 0; i < 5; i++ {
          fmt.Println(i)
      }
      

      Indica que declaramos una variable llamada i y fijamos el valor inicial en 0.

      A continuación, se encuentra la condición:

      for i := 0; i < 5; i++ {
          fmt.Println(i)
      }
      

      En esta condición, indicamos que aunque i es menor que el valor 5, el bucle debería continuar ejecutándose.

      Finalmente, se encuentra la posinstrucción:

      for i := 0; i < 5; i++ {
          fmt.Println(i)
      }
      

      En la posinstrucción, incrementamos la variable de bucle i en uno cada vez que se produce una iteración usando el operador de incremento i++.

      Cuando ejecutamos este programa, el resultado es similar al siguiente:

      Output

      0 1 2 3 4

      El bucle se ejecutó 5 veces. Inicialmente, se fijó i en 0 y luego se comprobó para ver si i era menor que 5. Debido a que el valor de i fue inferior a 5, se ejecutaron el bucle y la acción de fmt.PrintIn(i). Una vez finalizado el bucle, se invocó la posinstrucción i++ y el valor de i se incrementó en 1.

      Nota: Tenga en cuenta que en el terreno de la programación se suele tomar el índice 0 como punto de partida. Por ello, aunque se imprimen 5 números van de 0 a 4.

      No existe una limitación que impone comenzar en 0 o finalizar a un valor especificado. Podemos asignar cualquier valor a nuestra instrucción inicial y también definir el punto final en cualquier valor en nuestra posinstrucción. Esto nos permite crear cualquier intervalo deseado para el bucle:

      for i := 20; i < 25; i++ {
          fmt.Println(i)
      }
      

      Aquí, la iteración va de 20 (inclusivo) a 25 (exclusivo). Por lo tanto, el resultado tendrá este aspecto:

      Output

      20 21 22 23 24

      También podemos usar nuestra posinstrucción para el incremento en diferentes valores. Esto es similar a step en otros lenguajes:

      Primero, usaremos una posinstrucción con un valor positivo:

      for i := 0; i < 15; i += 3 {
          fmt.Println(i)
      }
      

      En este caso, el bucle for está configurado para que los números de 0 a 15 se impriman, aunque con un incremento de 3, con lo cual se imprime cada tercer número, de esta forma:

      Output

      0 3 6 9 12

      También podemos aplicar un valor negativo a nuestro argumento de posinstrucción para iteraciones hacia atrás, pero tendremos que ajustar nuestra instrucción inicial y los argumentos de condición como corresponde:

      for i := 100; i > 0; i -= 10 {
          fmt.Println(i)
      }
      

      Aquí, fijamos i en un valor inicial de 100, usamos la condición i < 0 para la detención en 0 y la posinstrucción aplica una reducción de 10 al valor con el operador -=. El bucle comienza en 100 y finaliza en 0; se aplica una disminución de 10 con cada iteración. Podemos ver que esto sucede en el resultado:

      Output

      100 90 80 70 60 50 40 30 20 10

      También puede excluir la instrucción inicial y la posinstrucción de la sintaxis de for, y solo usar la condición. Esto es conoce como bucle Condition:

      i := 0
      for i < 5 {
          fmt.Println(i)
          i++
      }
      

      Esta vez, declaramos la variable i de forma separada del bucle for en la línea de código anterior. El bucle solo tiene una clausula de condición que comprueba para ver si i es menor que 5. Siempre que la condición se evalúe a true, el bucle seguirá repitiéndose.

      A veces, es posible que no conozca el número de iteraciones que necesitará para completar una tarea concreta. En ese caso, puede omitir todas las instrucciones y usar la palabra clave break para cerrar la ejecución.

      for {
          if someCondition {
              break
          }
          // do action here
      }
      

      Un ejemplo de esto podría ser un caso en el que se realicen lecturas desde una estructura con un tamaño indeterminado, como un búfer, y no se conozca el momento en que la lectura finalizará.

      buffer.go

      package main
      
      import (
          "bytes"
          "fmt"
          "io"
      )
      
      func main() {
          buf := bytes.NewBufferString("onentwonthreenfourn")
      
          for {
              line, err := buf.ReadString('n')
              if err != nil {
                  if err == io.EOF {
      
                      fmt.Print(line)
                      break
                  }
                  fmt.Println(err)
                  break
              }
              fmt.Print(line)
          }
      }
      

      En el código anterior, buf :=bytes.NewBufferString("onentwonthreenfourn") declara un búfer con algunos datos. Debido a que no conocemos el momento en que el búfer terminará con la lectura, creamos un bucle for sin cláusula. Dentro del bucle for, usamos line, err := buf.ReadString('n') para leer una línea del búfer y comprobar si se produjo un error de lectura del búfer. Si se produjo un error, abordamos el error y usamos la palabra clave break para cerrar el bucle for. Con estos puntos break, no necesita incluir una condición para detener el bucle.

      A lo largo de esta sección, aprendió a declarar un bucle ForClause y usarlo para la iteración a través de un intervalo de valores conocido. También aprendió a usar un bucle “Condition” para iterarlo hasta que se cumpla una condición específica. A continuación, aprenderá sobre el uso que se da a RangeClause para la iteración a través de tipos de datos secuenciales.

      Aplicar bucles a través de tipos de datos secuenciales con RangeClause

      Es común en Go usar bucles for para iterar los elementos de tipos de datos secuenciales o de recopilación, como segmentos, matrices y cadenas. Para facilitar esto, podemos usar un bucle for con sintaxis de RangeClause. Aunque puede repetir tipos de datos secuenciales usando la sintaxis de ForClause, la RangeClause es más limpia y fácil de leer.

      Antes de que veamos la manera de usar una RangeClause, veremos la manera en que podemos repetir iterar un segmento usando la sintaxis ForClause:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for i := 0; i < len(sharks); i++ {
              fmt.Println(sharks[i])
          }
      }
      

      Al ejecutar esto, se obtendrá el siguiente resultado y imprimirá cada elemento del segmento:

      Output

      hammerhead great white dogfish frilled bullhead requiem

      Ahora, usaremos RangeClause para realizar el mismo conjunto de acciones:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for i, shark := range sharks {
              fmt.Println(i, shark)
          }
      }
      

      En este caso, imprimiremos cada elemento de la lista. Aunque usamos las variables i y shark, podríamos haber invocado la variable con cualquier otro nombre de variable válido y obtendríamos el mismo resultado:

      Output

      0 hammerhead 1 great white 2 dogfish 3 frilled 4 bullhead 5 requiem

      Cuando use range en un segmento, siempre mostrará dos valores. El primer valor será el índice en el que se encuentre la iteración actual del bucle, y el segundo será el valor de ese índice. En este caso, para la primera iteración, el índice fue 0 y el valor hammerhead.

      A veces, solo deseamos los valores dentro de los elementos de segmentos, no el índice. Si cambiamos el código anterior para que solo imprima el valor, veremos un error de tiempo de compilación:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for i, shark := range sharks {
              fmt.Println(shark)
          }
      }
      

      Output

      src/range-error.go:8:6: i declared and not used

      Debido a que i se declara en el bucle for, pero nunca se utiliza, el compilador responderá con el error i declared and not used. Éste es el mismo error que verá en Go cuando declare una variable y no la utilice.

      Debido a esto, Go cuenta con el identificador de espacios en blanco, que es un guión bajo (_). En un bucle for, puede usar el identificador de espacios en blanco para ignorar cualquier valor mostrado a partir de la palabra clave range. En este caso, nos conviene ignorar el índice, que es el primer argumento mostrado.

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for _, shark := range sharks {
              fmt.Println(shark)
          }
      }
      

      Output

      hammerhead great white dogfish frilled bullhead requiem

      Este resultado muestra que el bucle for se iteró a través del segmento de cadenas e imprimió cada elemento del segmento sin el índice.

      También puede usar range para añadir elementos a una lista:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for range sharks {
              sharks = append(sharks, "shark")
          }
      
          fmt.Printf("%qn", sharks)
      }
      

      Output

      ['hammerhead', 'great white', 'dogfish', 'frilled', 'bullhead', 'requiem', 'shark', 'shark', 'shark', 'shark', 'shark', 'shark']

      Aquí, añadimos una cadena de marcador de "shark" para cada elemento de la extensión del segmento sharks.

      Observe que no tuvimos que usar el identificador de espacios en blanco _ para ignorar valores de retorno del operador range. Go nos permite dejar afuera toda la parte de la declaración de la instrucción range si no necesitamos usar ninguno de los valores de retorno.

      También podemos usar el operador range para completar los valores de un segmento:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          integers := make([]int, 10)
          fmt.Println(integers)
      
          for i := range integers {
              integers[i] = i
          }
      
          fmt.Println(integers)
      }
      

      En este ejemplo, el segmento integers se inicia con diez valores vacíos, pero el bucle for establece todos los valores de la lista de esta forma:

      Output

      [0 0 0 0 0 0 0 0 0 0] [0 1 2 3 4 5 6 7 8 9]

      La primera vez que imprimimos el valor del segmento integers, lo único que vemos son ceros. A continuación, realizamos una iteración a través de cada índice y fijamos el valor en el índice actual. Luego, cuando imprimimos el valor de integers por segunda vez, se muestra que ahora todos tienen un valor de 0 a 9.

      También podemos usar el operador range para la iteración a través de cada carácter en una cadena:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sammy := "Sammy"
      
          for _, letter := range sammy {
              fmt.Printf("%cn", letter)
          }
      }
      

      Output

      S a m m y

      Cuando realicemos la iteración a través de un mapa, range mostrará la clave y el valor:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sammyShark := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
      
          for key, value := range sammyShark {
              fmt.Println(key + ": " + value)
          }
      }
      

      Output

      color: blue location: ocean name: Sammy animal: shark

      Nota: Es importante observar que el orden en el cual un mapa se muestra es aleatorio. Cada vez que ejecute este programa, es posible que obtenga un resultado diferente.

      Ahora que aprendió iterar datos secuenciales con bucles for range, veremos la forma de usar bucles dentro de bucles.

      Bucles for anidados

      Como en el caso de otros lenguajes de programación, es posible anidar bucles en Go. La anidación tiene lugar cuando hay una construcción dentro de otra. En este caso, un bucle anidado es un bucle que se produce dentro de otro. Estos pueden ser útiles cuando desea que una acción continua se realice sobre cada elemento de un conjunto de datos.

      Los bucles anidados tienen una estructura similar a la de las instrucciones if anidadas. Se construyen de la siguiente forma:

      for {
          [Action]
          for {
              [Action]  
          }
      }
      

      El programa primero encuentra el bucle externo y ejecuta su primera iteración. Esta primera iteración activa el bucle anidado interno, que luego se ejecuta hasta finalizar. Luego, el programa vuelve a la parte superior del bucle externo, completa la segunda iteración y de nuevo activa el bucle anidado. De nuevo, el bucle anidado se ejecuta hasta finalizar y el programa vuelve a la parte superior del bucle externo hasta que la secuencia se completa o un salto u otra instrucción interrumpa el proceso.

      Implementaremos un bucle for anidado para poder ver más de cerca. En este ejemplo, el bucle externo realizará la iteración en un segmento de enteros llamado numList y el bucle interno realizará iteraciones a través de un segmento de cadenas llamado alphaList.

      main.go

      package main
      
      import "fmt"
      
      func main() {
          numList := []int{1, 2, 3}
          alphaList := []string{"a", "b", "c"}
      
          for _, i := range numList {
              fmt.Println(i)
              for _, letter := range alphaList {
                  fmt.Println(letter)
              }
          }
      }
      

      Cuando ejecute este programa, verá el siguiente resultado:

      Output

      1 a b c 2 a b c 3 a b c

      El resultado muestra que el programa completa la primera iteración del bucle externo imprimiendo 1, lo que activa la finalización del bucle interno e imprime a, b y c de forma consecutiva. Una vez completado el bucle interno, el programa vuelve a la parte superior del bucle externo, imprime 2 y luego imprime de nuevo el bucle interno en su totalidad (a, b, y c), etc.

      Los bucles for anidados pueden ser útiles para iteraciones a través de elementos en segmentos compuestos de segmentos. En un segmento compuesto de segmentos, si usamos únicamente un bucle for, el programa producirá cada lista interna como un elemento:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          ints := [][]int{
              []int{0, 1, 2},
              []int{-1, -2, -3},
              []int{9, 8, 7},
          }
      
          for _, i := range ints {
              fmt.Println(i)
          }
      }
      

      Output

      [0 1 2] [-1 -2 -3] [9 8 7]

      Para acceder a cada elemento individual de los segmentos internos, implementaremos un bucle for anidado:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          ints := [][]int{
              []int{0, 1, 2},
              []int{-1, -2, -3},
              []int{9, 8, 7},
          }
      
          for _, i := range ints {
              for _, j := range i {
                  fmt.Println(j)
              }
          }
      }
      

      Output

      0 1 2 -1 -2 -3 9 8 7

      Cuando usamos un bucle for anidado aquí, podemos realizar iteraciones en los elementos individuales contenidos en los segmentos.

      Conclusión

      En este tutorial, aprendió a declarar y usar bucles for para resolver tareas repetitivas en Go. También aprendió las tres variaciones diferentes de un bucle for y la manera de usarlas. Para obtener más información sobre los bucles for y la forma de controlar el flujo de ellos, lea Cómo usar instrucciones Break y Continue cuando se trabaja con bucles en Go.



      Source link

      Usar instrucciones break y continue cuando se trabaja con bucles en Go


      Introducción

      Usar bucles for en Go le permite automatizar y repetir tareas de forma eficiente.

      Aprender a controlar el funcionamiento y el flujo de los bucles hará posible una lógica personalizada en su programa. Puede controlar sus bucles con las instrucciones break y continue.

      Instrucción break

      En Go, la instrucción break finaliza la ejecución del bucle actual. Una instrucción break casi siempre se sincroniza con una instrucción condicional if.

      Veamos un ejemplo en el que se utiliza la instrucción break en un bucle for:

      break.go

      package main
      
      import "fmt"
      
      func main() {
          for i := 0; i < 10; i++ {
              if i == 5 {
                  fmt.Println("Breaking out of loop")
                  break // break here
              }
              fmt.Println("The value of i is", i)
          }
          fmt.Println("Exiting program")
      }
      

      Este pequeño programa crea un bucle for que se iterará mientras i sea inferior a 10.

      En el bucle for, hay una instrucción if. La instrucción if prueba la condición de i para ver si el valor es inferior a 5. Si el valor de i no es igual a 5, el bucle continúa e imprime el valor de i. Si el valor de i es igual a 5, el bucle ejecuta la instrucción break, imprime Breaking out of loop y deja de ejecutarse. Al final del programa, imprimimos Exiting program para indicar que cerramos el bucle.

      Cuando ejecutemos este código, el resultado será el siguiente:

      Output

      The value of i is 0 The value of i is 1 The value of i is 2 The value of i is 3 The value of i is 4 Breaking out of loop Exiting program

      Esto muestra que una vez que se evalúa el entero i como equivalente a 5, el bucle se rompe porque se indica al programa que lo haga con la instrucción break.

      Bucles anidados

      Es importante recordar que la instrucción break solo detendrá la ejecución del bucle más interno en el que se invoca. Si tiene un conjunto de bucles anidados, necesitará una instrucción break para cada bucle, si lo desea.

      nested.go

      package main
      
      import "fmt"
      
      func main() {
          for outer := 0; outer < 5; outer++ {
              if outer == 3 {
                  fmt.Println("Breaking out of outer loop")
                  break // break here
              }
              fmt.Println("The value of outer is", outer)
              for inner := 0; inner < 5; inner++ {
                  if inner == 2 {
                      fmt.Println("Breaking out of inner loop")
                      break // break here
                  }
                  fmt.Println("The value of inner is", inner)
              }
          }
          fmt.Println("Exiting program")
      }
      

      En este programa, hay dos bucles. Aunque ambos bucles se repiten 5 veces, cada uno tiene una instrucción if condicional con una instrucción break. El bucle externo se interrumpirá si el valor de outer es igual a 3. El bucle interno se interrumpirá si el valor de inner es 2.

      Si ejecutamos el programa, veremos el siguiente resultado:

      Output

      The value of outer is 0 The value of inner is 0 The value of inner is 1 Breaking out of inner loop The value of outer is 1 The value of inner is 0 The value of inner is 1 Breaking out of inner loop The value of outer is 2 The value of inner is 0 The value of inner is 1 Breaking out of inner loop Breaking out of outer loop Exiting program

      Observe que cada vez que se interrumpe el bucle interno, no sucede lo mismo con el externo. Esto es porque break solo interrumpirá el bucle más interno desde el que se invoca.

      Hemos visto cómo el uso de break detendrá la ejecución de un bucle. A continuación, veremos la forma de continuar la iteración de un bucle.

      Instrucción continue

      La instrucción continue se usa cuando se busca omitir la parte restante del bucle, volver a la parte superior de este y continuar con una nueva iteración.

      Como en el caso de la instrucción break, la instrucción continue se utiliza comúnmente con una instrucción if condicional.

      Usando el mismo programa de bucle for que en la sección Instrucción break, emplearemos la instrucción continue en vez de break:

      continue.go

      package main
      
      import "fmt"
      
      func main() {
          for i := 0; i < 10; i++ {
              if i == 5 {
                  fmt.Println("Continuing loop")
                  continue // break here
              }
              fmt.Println("The value of i is", i)
          }
          fmt.Println("Exiting program")
      }
      

      La diferencia al usar la instrucción continue en vez de una instrucción break radica en que nuestro código continuará a pesar de la interrupción cuando la variable i se evalúe como equivalente a 5. Veamos el resultado:

      Output

      The value of i is 0 The value of i is 1 The value of i is 2 The value of i is 3 The value of i is 4 Continuing loop The value of i is 6 The value of i is 7 The value of i is 8 The value of i is 9 Exiting program

      Aquí vemos que la línea The value of i is 5 nunca se aparece en el resultado, pero el bucle continúa después de ese punto para imprimir líneas para los números 6 a 10 antes de cerrarse.

      Puede usar la instrucción continue para evitar código condicional profundamente anidado o para optimizar un bucle eliminando los casos frecuentes que desee rechazar.

      La instrucción continue hace que un programa omita determinados factores que surgen dentro de un bucle, pero luego continuará con resto de este.

      Conclusión

      Las instrucciones break y continue en Go le permitirán usar los bucles for de forma más eficaz en su código.



      Source link