One place for hosting & domains

      escribir

      Cómo escribir código asíncrono en Node.js


      El autor seleccionó a Open Internet/Free Speech Fund para recibir una donación como parte del programa Write for DOnations.

      Introducción

      En muchos programas de JavaScript, el código se ejecuta tal como el desarrollador lo escribe: línea por línea. Esto se conoce como ejecución síncrona, porque las líneas se ejecutan una después de la otra, en el orden en que se escribieron. Sin embargo, no todas las instrucciones proporcionadas a la computadora deben aplicarse de inmediato. Por ejemplo, si envía una solicitud de red, el proceso de ejecución de su código deberá esperar que los datos se muestren para poder utilizarlos. En este caso, se desperdiciaría tiempo si no se ejecutara otro código al esperar que la solicitud de red se complete. Para solucionar este problema, los desarrolladores utilizan la programación asíncrona, a través de la cual las líneas de código se ejecutan en un orden diferente del que se utilizó para su escritura. Con la programación asíncrona, podemos ejecutar otro código mientras esperamos que finalicen actividades prolongadas como las solicitudes de red.

      El código JavaScript se ejecuta en un solo hilo dentro de un proceso informático. Su código se procesa de forma sincrónica en este hilo y se ejecuta solo una instrucción a la vez. Por lo tanto, si hiciéramos una tarea de larga duración en este hilo, todo el código restante se bloquearía hasta que la tarea estuviera completa. Al aprovechar las funciones de programación asíncrona de JavaScript, podemos descargar las tareas de larga duración en un hilo en segundo plano para evitar este problema. Cuando se completa la tarea, el código que requerimos para procesar los datos de esta se vuelve a disponer en el hilo principal.

      A través de este tutorial, verá que en JavaScript se administran las tareas asíncronas con ayuda del bucle de eventos, que es una construcción de JavaScript que completa una nueva tarea mientras se espera otra. Luego creará un programa en el que se utiliza la programación asíncrona para solicitar una lista de películas a una API de Studio Ghibli y guardar los datos en un archivo CSV. El código asíncrono se escribirá de tres maneras: devoluciones de llamadas, promesas y las palabras claves deasync y await.

      Nota: A la fecha de la publicación de este artículo, en la programación asíncrona ya no se utiliza solo la devolución de llamadas, pero aprender este método obsoleto puede proporcionar una gran referencia respecto del motivo por el cual la comunidad de JavaScript ahora utiliza promesas. Las palabras claves async y await nos permiten usar promesas de una manera menos detallada y, por lo tanto, son la alternativa estándar para hacer programación asíncrona en JavaScript en el momento de la redacción de este artículo.

      Requisitos previos

      El bucle de eventos

      Comencemos estudiando el funcionamiento interno de la ejecución de funciones de JavaScript. Comprender la forma en que esto se comporta le permitirá escribir código asíncrono de forma más deliberada y le servirá solucionar problemas relacionados con el código en el futuro.

      A medida que en el intérprete de JavaScript se ejecuta el código, cada función invocada se añade a la pila de invocación de JavaScript. La pila de invocación es una pila: una estructura de datos similar a una lista cuyos elementos solo pueden añadirse y eliminarse al principio. En las pilas se sigue el principio “Último en entrar, primero en salir” o UEPS (LIFO). Si se añaden dos elementos en la pila, se eliminará primero el más reciente.

      Lo ilustraremos con un ejemplo usando la pila de invocación. Si en JavaScript se encuentra una función functionA() invocada, se añadirá a la pila de invocación. Si en la función functionA() se invoca otra función functionB(), entonces functionB() se añade al principio de la pila de invocación. Cuando en JavaScript se completa la ejecución de una función, se elimina de la pila de invocación. Por lo tanto, JavaScript ejecutará primero functionB(), la eliminará de la pila cuando termine y luego completará la ejecución de functionA() y la eliminará de la pila de invocación. Por está razón, las funciones internas siempre se ejecutan antes que las externas.

      Cuando en JavaScript se encuentra una operación asíncrona, como la de escribir en un archivo, se agrega a una tabla en la memoria. En esta tabla se almacena la operación, la condición para que se complete y la función que se invocará cuando se complete. A medida que la operación se completa, en JavaScript se añade la función asociada a la cola de mensajes. Una cola es otra estructura de datos en forma de lista en la que los elementos solo pueden añadirse al final y eliminarse al principio. En la cola de mensajes, si dos o más operaciones asíncronas están listas para que se ejecuten sus funciones, la función de la operación asíncrona que se complete primero se marcará para ejecutarse primero.

      Las funciones se encuentran en espera para su adición a la pila de invocación en la cola de mensajes. El bucle de eventos es un proceso perpetuo en el que se verifica si la pila de invocación está vacía. Si es así, el primer elemento de la cola de mensajes se mueve a la pila de invocación. En JavaScript, se da prioridad a las funciones en la cola de mensajes respecto de la invocación de funciones que interpreta en el código. El efecto combinado de la pila de invocación, la cola de mensajes y el bucle de eventos permite procesar el código de JavaScript mientras se administran actividades asíncronas.

      Ahora que comprende bien el bucle de eventos, sabe cómo se ejecutará el código asíncrono que escribió. Con este conocimiento, ahora podrá crear código asíncrono usando tres enfoques diferentes: devolución de llamadas, promesas, y async y await.

      Programación asíncrona con devolución de llamadas

      Una función de devolución de llamada es aquella que se pasa como argumento a otra función y luego se ejecuta cuando la otra función se completa. Usamos devoluciones de llamadas para garantizar que el código se ejecute solo después de que se completa una operación asíncrona.

      Durante mucho tiempo, las devoluciones de llamadas fueron el mecanismo más común para escribir código asíncrono, pero ahora se volvieron obsoletas en gran parte porque pueden dificultar la lectura del código. En este paso, escribirá un código asíncrono de ejemplo usando las devoluciones de llamadas a fin de poder utilizarlo como base para ver el aumento de la eficiencia en comparación con otras estrategias.

      Existen muchas formas de usar las funciones de devolución de llamadas en otra función. Generalmente, se utiliza la siguiente estructura:

      function asynchronousFunction([ Function Arguments ], [ Callback Function ]) {
          [ Action ]
      }
      

      Aunque no es requisito sintáctico de JavaScript ni de Node.js que la función de devolución de llamada sea el último argumento de la función externa, es una práctica común que facilita la identificación de las devoluciones de llamadas. También es común que los desarrolladores de JavaScript utilicen una función anónima como devolución de llamada. Las funciones anónimas son aquellas que se crean sin nombre. Una función suele ser mucho más legible cuando se define al final de la lista de argumentos.

      Para demostrar las devoluciones de llamadas, crearemos un módulo Node.js que se escribe una lista de películas de Studio Ghibli en un archivo. Primero, cree una carpeta en la que se almacenará nnuestro archivo de JavaScript y su resultado:

      Luego acceda a esa carpeta:

      Comenzaremos realizando una solicitud HTTP al API de Studio Ghibli, cuyos resultados se registrarán a través de nuestra función de devolución de llamadas. Para hacer esto, instalaremos una biblioteca que nos permita acceder a los datos de una respuesta HTTP en una devolución de llamada.

      En su terminal, inicie npm para que podamos tener una referencia para nuestros paquetes más adelante:

      A continuación, instale la biblioteca request:

      Ahora, abra un nuevo archivo llamado callbackMovies.js en un editor de texto como nano:

      En su editor de texto, introduzca el código siguiente. Comenzaremos enviando una solicitud HTTP con el módulo request:

      callbackMovies.js

      const request = require('request');
      
      request('https://ghibliapi.herokuapp.com/films');
      

      En la primera línea, cargaremos el módulo request que se instaló a través de npm. En el módulo se muestra una función en la que se pueden hacer solicitudes HTTP; luego guardaremos esa función en la constante request.

      Después, hacemos la solicitud HTTP usando la función request(). Ahora, imprimiremos los datos de la solicitud HTTP en la consola añadiendo los siguientes cambios resaltados:

      callbackMovies.js

      const request = require('request');
      
      request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
          if (error) {
              console.error(`Could not send request to API: ${error.message}`);
              return;
          }
      
          if (response.statusCode != 200) {
              console.error(`Expected status code 200 but received ${response.statusCode}.`);
              return;
          }
      
          console.log('Processing our list of movies');
          movies = JSON.parse(body);
          movies.forEach(movie => {
              console.log(`${movie['title']}, ${movie['release_date']}`);
          });
      });
      

      Cuando usamos la función request(), le asignamos dos parámetros:

      • la URL del sitio web que intentamos solicitar;
      • una función de devolución de llamada que se ocupa de cualquier error o respuesta exitosa una vez que se completa la solicitud.

      En nuestra función de devolución de llamada existen tres argumentos: error, response y body. Cuando la solicitud HTTP se completa, se otorgan automáticamente valores a los argumentos dependiendo del resultado. Si la solicitud no se enviara, error contendría un objeto. Sin embargo, response y body tendrían el valor null. Si la solicitud se realizó correctamente, la respuesta HTTP se almacenará en response. Si en nuestra respuesta HTTP se muestran datos (en este ejemplo obtenemos JSON), los datos se establecen en body.

      En nuestra función de devolución de llamada primero se verifica si se muestra un error. Es recomendable verificar primero si hay errores en una devolución de llamada para que la ejecución de esta no continúe con datos faltantes. En este caso, registramos el error y la ejecución de la función. Luego, verificamos el código de estado de la respuesta. Es posible que nuestro servidor no esté siempre disponible. A su vez, las API pueden cambiar. Esto hará que las solicitudes que una vez fueron razonables pasen a ser incorrectas. Al verificar que el código de estado sea 200, lo cual significa que la solicitud fue “OK”, podemos tener la confianza de que nuestra respuesta sea lo que esperábamos.

      Por último, analizamos el cuerpo de respuesta de un Array e iteramos cada película para registrar su nombre y año de estreno.

      Después de guardar y cerrar el archivo, ejecute esta secuencia de comandos con lo siguiente:

      Verá el siguiente resultado:

      Output

      Castle in the Sky, 1986 Grave of the Fireflies, 1988 My Neighbor Totoro, 1988 Kiki's Delivery Service, 1989 Only Yesterday, 1991 Porco Rosso, 1992 Pom Poko, 1994 Whisper of the Heart, 1995 Princess Mononoke, 1997 My Neighbors the Yamadas, 1999 Spirited Away, 2001 The Cat Returns, 2002 Howl's Moving Castle, 2004 Tales from Earthsea, 2006 Ponyo, 2008 Arrietty, 2010 From Up on Poppy Hill, 2011 The Wind Rises, 2013 The Tale of the Princess Kaguya, 2013 When Marnie Was There, 2014

      Obtuvimos con éxito una lista de películas de Studio Ghibli con el año en que se estrenaron. Ahora, terminaremos este programa escribiendo la lista de películas que actualmente registramos en un archivo.

      Actualice el archivo callbackMovies.js en su editor de texto para incluir el siguiente código resaltado, que crea un archivo CSV con los datos de nuestras películas:

      callbackMovies.js

      const request = require('request');
      const fs = require('fs');
      
      request('https://ghibliapi.herokuapp.com/films', (error, response, body) => {
          if (error) {
              console.error(`Could not send request to API: ${error.message}`);
              return;
          }
      
          if (response.statusCode != 200) {
              console.error(`Expected status code 200 but received ${response.statusCode}.`);
              return;
          }
      
          console.log('Processing our list of movies');
          movies = JSON.parse(body);
          let movieList = '';
          movies.forEach(movie => {
              movieList += `${movie['title']}, ${movie['release_date']}n`;
          });
      
          fs.writeFile('callbackMovies.csv', movieList, (error) => {
              if (error) {
                  console.error(`Could not save the Ghibli movies to a file: ${error}`);
                  return;
              }
      
              console.log('Saved our list of movies to callbackMovies.csv');;
          });
      });
      

      Observando los cambios resaltados, podemos ver que importamos el módulo fs. Este módulo forma parte de la configuración estándar de todas las instalaciones de Node.js y contiene un método writeFile() que puede escribir en un archivo de forma asíncrona.

      En lugar de registrar los datos en la consola, ahora los añadiremos a una variable de cadena movieList. Luego, usaremos writeFile() para guardar el contenido de movieList en un archivo nuevo: callbackMovies.csv. Por último, proporcionaremos una devolución de llamada a la función writeFile(), que tiene un argumento: error. Esto nos permite manejar los casos en los que no podemos escribir en un archivo; por ejemplo, cuando el usuario en el que se ejecuta el proceso node no tiene esos permisos.

      Guarde el archivo y ejecute este programa de Node.js una vez más con lo siguiente:

      En su carpeta ghibliMovies, visualizará callbackMovies.csv, que tiene el siguiente contenido:

      callbackMovies.csv

      Castle in the Sky, 1986
      Grave of the Fireflies, 1988
      My Neighbor Totoro, 1988
      Kiki's Delivery Service, 1989
      Only Yesterday, 1991
      Porco Rosso, 1992
      Pom Poko, 1994
      Whisper of the Heart, 1995
      Princess Mononoke, 1997
      My Neighbors the Yamadas, 1999
      Spirited Away, 2001
      The Cat Returns, 2002
      Howl's Moving Castle, 2004
      Tales from Earthsea, 2006
      Ponyo, 2008
      Arrietty, 2010
      From Up on Poppy Hill, 2011
      The Wind Rises, 2013
      The Tale of the Princess Kaguya, 2013
      When Marnie Was There, 2014
      

      Es importante observar que escribimos en nuestro archivo CSV en la devolución de llamada de la solicitud HTTP. Una vez que el código se encuentra en la función de devolución de llamada, solo escribirá en el archivo después de que se haya completado la solicitud HTTP. Si quisiéramos comunicarnos con una base de datos después de escribir nuestro archivo CSV, crearíamos otra función asíncrona que se invocaría en la devolución de llamada de nuestro writeFile(). Mientras más código asíncrono tengamos, más funciones de devolución de llamada deberán anidarse.

      Imaginemos que queremos ejecutar cinco operaciones asíncronas, cada una de las cuales solo se puede ejecutar cuando otra se complete. Si codificáramos esto, tendríamos algo como lo siguiente:

      doSomething1(() => {
          doSomething2(() => {
              doSomething3(() => {
                  doSomething4(() => {
                      doSomething5(() => {
                          // final action
                      });
                  });
              });
          });
      });
      

      Cuando en las devoluciones de llamada anidadas hay muchas líneas de código para ejecutar, se vuelven considerablemente más complejas e ilegibles. A medida que aumenten el tamaño y la complejidad de su proyecto de JavaScript, este efecto se hará más pronunciado hasta que finalmente no pueda manejarse. Debido a esto, los desarrolladores ya no utilizan las devoluciones de llamada para manejar las operaciones asíncronas. Para mejorar la sintaxis de nuestro código asíncrono, podemos usar promesas como alternativa.

      Usar promesas para la programación asíncrona concisa

      Una promesa es un objeto de JavaScript en el que se mostrará un valor en algún momento del futuro. En las funciones asíncronas se pueden mostrar objetos de promesas en lugar de valores concretos. Si obtenemos un valor en el futuro, afirmamos que la promesa se cumplió. Si obtenemos un error en el futuro, afirmamos que la promesa se rechazó. De lo contrario, se siguen realizando tareas vinculadas a la promesa en un estado de operación pendiente.

      Las promesas suelen adoptar la siguiente forma:

      promiseFunction()
          .then([ Callback Function for Fulfilled Promise ])
          .catch([ Callback Function for Rejected Promise ])
      

      Como se muestra en esta plantilla, en las promesas también se utilizan las funciones de devolución de llamada. Tenemos una función de devolución de llamada para el método then(), que se ejecuta cuando se cumple una promesa. También tenemos una función de devolución de llamada para que en el método catch() se pueda manejar cualquier error que se produzca mientras la promesa está en ejecución.

      Obtengamos experiencia de primera mano con las promesas reescribiendo nuestro programa de Studio Ghibli para usar estas en su lugar.

      Axios es un cliente HTTP basado en promesas para JavaScript; lo instalaremos:

      Ahora, con su editor de texto preferido, cree un archivo nuevo promiseMovies.js:

      En nuestro programa, se realizará una solicitud HTTP con axios y luego se utilizará una versión especial de fs basada en promesas para guardar el guardado en un nuevo archivo CSV.

      Escriba este código en promiseMovies.js para que podamos cargar Axios y enviar una solicitud HTTP a la API de películas:

      promiseMovies.js

      const axios = require('axios');
      
      axios.get('https://ghibliapi.herokuapp.com/films');
      

      En la primera línea, cargamos el módulo axios y almacenamos la función mostrada en una constante llamada axios. Luego, usamos el método axios.get() para enviar una solicitud HTTP a la API.

      Con el método axios.get() se obtiene una promesa. Encadenaremos esa promesa para poder imprimir la lista de películas de Ghibli en la consola:

      promiseMovies.js

      const axios = require('axios');
      const fs = require('fs').promises;
      
      
      axios.get('https://ghibliapi.herokuapp.com/films')
          .then((response) => {
              console.log('Successfully retrieved our list of movies');
              response.data.forEach(movie => {
                  console.log(`${movie['title']}, ${movie['release_date']}`);
              });
          })
      

      Desglosaremos lo que está sucediendo. Después de realizar una solicitud HTTP GET con axios.get(), usamos la función then(), que se ejecuta solo cuando la promesa se cumple. En este caso, imprimimos las películas en la pantalla al igual que en el ejemplo de devoluciones de llamadas.

      Para mejorar este programa, agregue el código resaltado para escribir los datos HTTP en un archivo:

      promiseMovies.js

      const axios = require('axios');
      const fs = require('fs').promises;
      
      
      axios.get('https://ghibliapi.herokuapp.com/films')
          .then((response) => {
              console.log('Successfully retrieved our list of movies');
              let movieList = '';
              response.data.forEach(movie => {
                  movieList += `${movie['title']}, ${movie['release_date']}n`;
              });
      
              return fs.writeFile('promiseMovies.csv', movieList);
          })
          .then(() => {
              console.log('Saved our list of movies to promiseMovies.csv');
          })
      

      Además, importaremos el módulo fs una vez más. Observe que después de la importación fs obtenemos .promises. Node.js incluye una versión basada en promesas de la biblioteca fs basada en devoluciones de llamadas, por lo que la compatibilidad con versiones anteriores se mantiene en los proyectos heredados.

      La primera función then(), en la que se procesa la solicitud HTTP, ahora invoca fs.writeFile() en lugar de realizar impresiones en la consola. Debido a que importamos la versión basada en promesas de fs, nuestra función writeFile() muestra otra promesa. Por lo tanto, añadimos otra función then() para cuando se cumpla la promesa de writeFile().

      Una promesa puede mostrar una nueva promesa, lo que nos permite ejecutarlas una después de la otra. Esto nos permite realizar varias operaciones asíncronas. Esto se conoce como encadenamiento de promesas y es análogo a la anidación de devoluciones de llamada. El segundo then() solo se invoca una vez que se escribe con éxito en el archivo.

      Nota: En este ejemplo, no revisamos el código de estado HTTP como en el ejemplo de devolución de llamada. Por defecto, en axios no se cumple la promesa si se obtiene un código de estado que indica un error. Por lo tanto, ya no necesitamos validarlo.

      Para completar este programa, encadene la promesa con una función catch(), como se resalta en lo siguiente:

      promiseMovies.js

      const axios = require('axios');
      const fs = require('fs').promises;
      
      
      axios.get('https://ghibliapi.herokuapp.com/films')
          .then((response) => {
              console.log('Successfully retrieved our list of movies');
              let movieList = '';
              response.data.forEach(movie => {
                  movieList += `${movie['title']}, ${movie['release_date']}n`;
              });
      
              return fs.writeFile('promiseMovies.csv', movieList);
          })
          .then(() => {
              console.log('Saved our list of movies to promiseMovies.csv');
          })
          .catch((error) => {
              console.error(`Could not save the Ghibli movies to a file: ${error}`);
          });
      

      Si alguna promesa no se cumple en la cadena de promesas, JavaScript se dirige automáticamente a la función catch() si es que se definió. Es por eso que solo tenemos una cláusula catch() aunque tengamos dos operaciones asíncronas.

      Confirmaremos que nuestro programa produce el mismo resultado ejecutando lo siguiente:

      En su carpeta ghibliMovies, verá el archivo promiseMovies.csv que contiene lo siguiente:

      promiseMovies.csv

      Castle in the Sky, 1986
      Grave of the Fireflies, 1988
      My Neighbor Totoro, 1988
      Kiki's Delivery Service, 1989
      Only Yesterday, 1991
      Porco Rosso, 1992
      Pom Poko, 1994
      Whisper of the Heart, 1995
      Princess Mononoke, 1997
      My Neighbors the Yamadas, 1999
      Spirited Away, 2001
      The Cat Returns, 2002
      Howl's Moving Castle, 2004
      Tales from Earthsea, 2006
      Ponyo, 2008
      Arrietty, 2010
      From Up on Poppy Hill, 2011
      The Wind Rises, 2013
      The Tale of the Princess Kaguya, 2013
      When Marnie Was There, 2014
      

      Al usar promesas, podemos escribir código mucho más conciso que al emplear únicamente devoluciones de llamadas. La cadena de promesas de devoluciones de llamadas es una opción más ordenada que la anidación de devoluciones de llamadas. Sin embargo, a medida que realicemos más invocaciones asíncronas, nuestra cadena de promesas se vuelve más larga y difícil de mantener.

      El nivel de detalle de las devoluciones de llamada y las promesas se debe a la necesidad de crear funciones cuando tenemos el resultado de una tarea asíncrona. Una mejor idea sería esperar un resultado asíncrono y disponerlo en una variable fuera de la función. De esta manera, podemos usar los resultados de las variables sin tener que crear una función. Podemos lograr esto con las palabras claves async y await.

      Escribir JavaScript con async y await

      Las palabras claves async y await proporcionan una sintaxis alternativa al trabajar con promesas. En lugar de tener el resultado de una promesa disponible en el método then(), el resultado se devuelve como un valor igual que en cualquier otra función. Definiremos una función con la palabra clave async para que se indique en JavaScript que es una función asíncrona que muestra una promesa. Usamos la palabra clave await para indicar en JavaScript que se muestren los resultados de la promesa en lugar de la propia promesa cuando se cumpla.

      En general, cuando se usan async y await el panorama es similar al siguiente:

      async function() {
          await [Asynchronous Action]
      }
      

      Veamos la manera en que async y await pueden mejorar nuestro programa de Studio Ghibli. Utilice su editor de texto para crear y abrir un archivo nuevo syncAwaitMovies.js:

      En su archivo de JavaScript recién abierto, empezaremos por importar los mismos módulos que usamos en nuestro ejemplo de promesas:

      asyncAwaitMovies.js

      const axios = require('axios');
      const fs = require('fs').promises;
      

      Las importaciones son iguales que promiseMovies.js porque en async y await se utilizan promesas.

      Ahora, usaremos la palabra clave async para crear una función con nuestro código asíncrono:

      asyncAwaitMovies.js

      const axios = require('axios');
      const fs = require('fs').promises;
      
      async function saveMovies() {}
      

      Crearemos una nueva función llamada saveMovies() pero incluiremos async al principio de su definición. Esto es importante, ya que solo podemos usar la palabra clave await en una función asíncrona.

      Utilice la palabra clave await para realizar una solicitud HTTP en la que se obtenga la lista de películas de la API de Ghibli:

      asyncAwaitMovies.js

      const axios = require('axios');
      const fs = require('fs').promises;
      
      async function saveMovies() {
          let response = await axios.get('https://ghibliapi.herokuapp.com/films');
          let movieList = '';
          response.data.forEach(movie => {
              movieList += `${movie['title']}, ${movie['release_date']}n`;
          });
      }
      

      En nuestra función saveMovies(), realizaremos una solicitud HTTP con axios.get() como antes. Esta vez, no la encadenamos con una función then(). En su lugar, añadiremos await antes de su invocación. Cuando JavaScript detecte await, solo ejecutará el código restante de la función después que axios.get() finalice la ejecución y configure la variable response. En el otro código se guardan los datos de las películas para que podamos escribir en un archivo.

      Escribiremos los datos de las películas en un archivo:

      asyncAwaitMovies.js

      const axios = require('axios');
      const fs = require('fs').promises;
      
      async function saveMovies() {
          let response = await axios.get('https://ghibliapi.herokuapp.com/films');
          let movieList = '';
          response.data.forEach(movie => {
              movieList += `${movie['title']}, ${movie['release_date']}n`;
          });
          await fs.writeFile('asyncAwaitMovies.csv', movieList);
      }
      

      También usaremos la palabra clave await cuando escribamos en un archivo con fs.writeFile().

      Para completar esta función, debemos capturar los errores que nuestras promesas puedan producir. Lo haremos encapsulando nuestro código en un bloque try y catch:

      asyncAwaitMovies.js

      const axios = require('axios');
      const fs = require('fs').promises;
      
      async function saveMovies() {
          try {
              let response = await axios.get('https://ghibliapi.herokuapp.com/films');
              let movieList = '';
              response.data.forEach(movie => {
                  movieList += `${movie['title']}, ${movie['release_date']}n`;
              });
              await fs.writeFile('asyncAwaitMovies.csv', movieList);
          } catch (error) {
              console.error(`Could not save the Ghibli movies to a file: ${error}`);
          }
      }
      
      

      Debido a que las promesas pueden fallar, encapsularemos nuestro código asíncrono con una cláusula try y catch. Con esto se capturarán todos los errores que se produzcan cuando las solicitudes HTTP o las operaciones de escritura en archivos fallen.

      Por último, invocaremos nuestra función asíncrona saveMovies() para que se ejecute cuando iniciemos el programa con node.

      asyncAwaitMovies.js

      const axios = require('axios');
      const fs = require('fs').promises;
      
      async function saveMovies() {
          try {
              let response = await axios.get('https://ghibliapi.herokuapp.com/films');
              let movieList = '';
              response.data.forEach(movie => {
                  movieList += `${movie['title']}, ${movie['release_date']}n`;
              });
              await fs.writeFile('asyncAwaitMovies.csv', movieList);
          } catch (error) {
              console.error(`Could not save the Ghibli movies to a file: ${error}`);
          }
      }
      
      saveMovies();
      

      A simple vista, parece un típico bloque de código síncrono de JavaScript. Tiene menos funciones que se pasan de un lado a otro, por lo que se ve más ordenado. Estos pequeños ajustes hacen que resulte más sencillo mantener el código asíncrono con async y await.

      Pruebe esta iteración de nuestro programa ingresando lo siguiente en su terminal:

      En su carpeta ghibliMovies, se creará un nuevo archivo asyncAwaitMovies.csv con el siguiente contenido:

      asyncAwaitMovies.csv

      Castle in the Sky, 1986
      Grave of the Fireflies, 1988
      My Neighbor Totoro, 1988
      Kiki's Delivery Service, 1989
      Only Yesterday, 1991
      Porco Rosso, 1992
      Pom Poko, 1994
      Whisper of the Heart, 1995
      Princess Mononoke, 1997
      My Neighbors the Yamadas, 1999
      Spirited Away, 2001
      The Cat Returns, 2002
      Howl's Moving Castle, 2004
      Tales from Earthsea, 2006
      Ponyo, 2008
      Arrietty, 2010
      From Up on Poppy Hill, 2011
      The Wind Rises, 2013
      The Tale of the Princess Kaguya, 2013
      When Marnie Was There, 2014
      

      De esta manera, habrá utilizado las funciones de JavaScript async y await para administrar código asíncrono.

      Conclusión

      A través de este tutorial, aprendió sobre la forma en que JavaScript maneja las funciones de ejecución y administra las operaciones asíncronas con el bucle de eventos. Luego, escribió programas en los que se creó un archivo CSV después de realizar una solicitud HTTP para datos de películas utilizando varias técnicas de programación asíncrona. Primero, utilizó el enfoque obsoleto basado en la devolución de llamadaa. Luego utilizó promesas y, por último, async y await para hacer que la sintaxis de estas fuera más sucinta.

      Al comprender el código asíncrono con Node.js, ahora puede desarrollar programas en los que se aprovechen los beneficios de la programación asíncrona, como los que dependen de las invocaciones de API. Consulte esta lista de API públicas. Para usarlas, tendrá que hacer solicitudes HTTP asíncronas como las que hicimos en este tutorial. Para un aprendizaje más profundo, intente crear una aplicación en la que se utilicen estas API a fin de poner en práctica las técnicas que aprendió aquí.



      Source link

      Cómo escribir comentarios en Go


      Introducción

      Los comentarios son líneas que existen en los programas informáticos y que los compiladores e intérpretes ignoran. Incluir comentarios en programas hace que el código sea más legible para los seres humanos, ya que proporciona información o explicaciones sobre lo que cada parte de un programa hace.

      Según el propósito de su programa, los comentarios pueden servir como notas o recordatorios, o pueden estar escritos con la intención de que otros programadores puedan comprender lo que su código hace.

      En general, es recomendable escribir comentarios mientras se escribe o se actualiza un programa, ya que se puede olvidar fácilmente el proceso de pensamiento y los comentarios que se introducen después pueden ser menos útiles a largo plazo.

      Sintaxis de los comentarios

      Los comentarios de Go comienzan con un conjunto de barras diagonales (//) y continúan hasta el final de la línea. Corresponde disponer de un espacio en blanco después del conjunto de barras diagonales.

      Generalmente, los comentarios tendrán un aspecto similar a este:

      // This is a comment
      

      Los comentarios no se ejecutan, por lo que no habrá indicaciones de comentarios al ejecutar un programa. Los comentarios se encuentran en el código fuente para que los seres humanos puedan leerlos, no para que las computadoras los ejecuten.

      En un programa “¡Hello, World!”, un comentario puede tener el siguiente aspecto:

      hello.go

      package main
      
      import (
          "fmt"
      )
      
      func main() {
          // Print “Hello, World!” to console
          fmt.Println("Hello, World!")
      }
      
      

      En un bucle for que itera un segmento, los comentarios pueden verse así:

      sharks.go

      package main
      
      import (
          "fmt"
      )
      
      func main() {
          // Define sharks variable as a slice of strings
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          // For loop that iterates over sharks list and prints each string item
          for _, shark := range sharks {
              fmt.Println(shark)
          }
      }
      

      Los comentarios deberían hacerse en la misma sangría que el código al que se aplican. Es decir, una definición de función sin sangría tendría un comentario sin guión, y cada nivel de sangría siguiente tendría comentarios en línea con el código al que se aplican.

      Por ejemplo, aquí se muestra la forma en que se comenta la función main, con comentarios después de cada nivel de sangría del código:

      color.go

      package main
      
      import "fmt"
      
      const favColor string = "blue"
      
      func main() {
          var guess string
          // Create an input loop
          for {
              // Ask the user to guess my favorite color
              fmt.Println("Guess my favorite color:")
              // Try to read a line of input from the user. Print out the error 0
              if _, err := fmt.Scanln(&guess); err != nil {
                  fmt.Printf("%sn", err)
                  return
              }
              // Did they guess the correct color?
              if favColor == guess {
                  // They guessed it!
                  fmt.Printf("%q is my favorite color!n", favColor)
                  return
              }
              // Wrong! Have them guess again.
              fmt.Printf("Sorry, %q is not my favorite color. Guess again.n", guess)
          }
      }
      

      Los comentarios se hacen para ayudar a los programadores, así se trate del programador original o de alguien que utilice el proyecto o colabore en él. Si los comentarios no pueden mantenerse ni actualizarse de forma adecuada con la base de código, es mejor no incluir un comentario en lugar de escribir uno que contradiga el código o pueda hacerlo en el futuro.

      Al ingresar comentarios en el código, debería intentar dilucidar el por qué del código en lugar del qué o el cómo. A menos que el código sea particularmente complicado, con mirarlo generalmente basta para responder interrogantes como qué o cómo, razón por la cual los comentarios generalmente se centran en el por qué.

      Comentarios de bloque

      Los comentarios de bloque pueden utilizarse para explicar código más complicado o del que no espera conocimiento de parte del lector.

      En Go, puede crear comentarios de bloques de dos formas. La primera consiste en usar un conjunto de dobles barras inclinadas y repetirlas para cada línea.

      // First line of a block comment
      // Second line of a block comment
      

      La segunda,en usar etiquetas de apertura (/*) y etiquetas de cierre (*/​​​). Para documentar el código, se considera adecuado usar siempre sintaxis de //. Sólo usarías la sintaxis /* ... */​​​ para depuración, tema que abarcaremos más adelante en este artículo.

      /*
      Everything here
      will be considered
      a block comment
      */
      

      En este ejemplo, el comentario de bloque define lo que sucede en la función MustGet():

      function.go

      // MustGet will retrieve a url and return the body of the page.
      // If Get encounters any errors, it will panic.
      func MustGet(url string) string {
          resp, err := http.Get(url)
          if err != nil {
              panic(err)
          }
      
          // don't forget to close the body
          defer resp.Body.Close()
          var body []byte
          if body, err = ioutil.ReadAll(resp.Body); err != nil {
              panic(err)
          }
          return string(body)
      }
      

      Es común ver comentarios de bloque al inicio de las funciones exportadas en Go: estos comentarios también son los que generan la documentación de su código. Los comentarios de bloque se utilizan también cuando las operaciones son menos sencillas y, por lo tanto, exigen una explicación completa. Salvo en el caso de la documentación de funciones, debería intentar evitar el exceso de comentarios sobre el código y confiar en la capacidad de otros programadores para comprender Go, a menos que escriba para un público en particular.

      Comentarios incorporados

      Los comentarios incorporados se producen en la misma línea de una instrucción, siguiendo el propio código. Al igual que otros comentarios, comienzan con una serie de barras diagonales. Una vez más, no es necesario incluir un espacio en blanco después de las barras, pero se considera apropiado hacerlo.

      Generalmente, los comentarios incorporados tienen el siguiente aspecto:

      [code]  // Inline comment about the code
      

      Los comentarios en línea deberían utilizarse de forma racional, pero pueden ser eficaces para explicar partes complicadas o no obvias del código. También pueden ser útiles si cree que en el futuro es posible que no recuerde una línea del código que escribe, o bien si colabora con alguien que sepa que no esté familiarizado con todos los aspectos del código.

      Por ejemplo, si no recurre mucho a la matemática en sus programas de Go, es posible que usted o sus colaboradores no sepan que con lo siguiente se crea un número complejo, por lo que posiblemente desee incluir un comentario incorporado sobre eso:

      z := x % 2  // Get the modulus of x
      

      También puede usar comentarios en línea para explicar los motivos de una acción o proporcionar información adicional, como en el siguiente caso:

      x := 8  // Initialize x with an arbitrary number
      

      Debería usar comentarios en línea solo cuando sea necesario y cuando puedan proporcionar orientación útil para la persona que lea el programa.

      Comentar código para pruebas

      Además de usar comentarios como una forma de documentar código, también puede usar etiquetas de apertura (/*) y cierre (*/) para crear un comentario de bloque. Esto le permite hacer comentarios sobre código que no desee ejecutar mientras pruebe o depure un programa en proceso de creación. Es decir, cuando experimente errores después de implementar nuevas líneas de código, es posible que quiera comentar algunas de ellas para ver si puede resolver el problema puntual.

      Las etiquetas /* y */ también pueden permitirle probar alternativas mientras determinan la manera de configurar su código. También puede usar comentarios de bloque para comentar código que produce errores mientras continúa trabajando en otras partes de su código.

      multiply.go

      // Function to add two numbers
      func addTwoNumbers(x, y int) int {
          sum := x + y
          return sum
      }
      
      // Function to multiply two numbers
      func multiplyTwoNumbers(x, y int) int {
          product := x * y
          return product
      }
      
      func main() {
          /*
              In this example, we're commenting out the addTwoNumbers
              function because it is failing, therefore preventing it from executing.
              Only the multiplyTwoNumbers function will run
      
              a := addTwoNumbers(3, 5)
              fmt.Println(a)
      
          */
      
          m := multiplyTwoNumbers(5, 9)
          fmt.Println(m)
      }
      

      Nota: Solo se deberían agregar comentarios al código para pruebas. No deje fragmentos de código con comentarios en la versión final de su programa.

      Comentar código con las etiquetas /* y */ puede permitirle probar diferentes métodos de programación, así como ayudarlo a encontrar el origen de un error comentando y ejecutando partes de un programa de forma sistemática.

      Conclusión

      El uso comentarios en sus programas de Go le permite hacer que estos últimos sean más legibles para los humanos, lo cual lo incluye a usted mismo en el futuro. Al añadir comentarios apropiados que sean pertinentes y útiles, puede hacer que resulte más sencillo para otros colaborar con usted en los proyectos de programación y hacer que el valor de su código sea más obvio.

      Al comentar su código de forma adecuada en Go, también podrá usar la herramienta Godoc. Godoc es una herramienta que extraerá comentarios de su código y generará documentación para su programa de Go.



      Source link

      Cómo escribir instrucciones condicionales en Go


      Introducción

      Las instrucciones condicionales son parte de cada lenguaje de programación. Con las instrucciones condicionales, podemos disponer de código que a veces se ejecuta y que en otros momentos no lo hace, según las condiciones del programa en ese momento.

      Cuando ejecutamos por completo cada instrucción de un programa, no pedimos a este que evalúe condiciones específicas. Al usar las instrucciones condicionales, los programas pueden determinar si se cumplen ciertas condiciones y luego recibir instrucciones sobre cómo proceder a continuación.

      Veamos algunos ejemplos en los que usaríamos instrucciones condicionales:

      • Si el estudiante recibe más del 65 % en su examen, informar que obtuvo una calificación de aprobación; si no, informar que obtuvo una calificación de desaprobación.
      • Si posee dinero en su cuenta, calcular intereses; si no, cobrar una penalización.
      • Si compra 10 o más naranjas, calcular un descuento del 5 %; si compra menos, no hacerlo.

      Al evaluar las condiciones y asignar un código para que se ejecute según si se cumplan o no estas condiciones, escribimos código condicional.

      Este tutorial le servirá como guía para escribir instrucciones condicionales en el lenguaje de programación Go.

      Instrucciones “if”

      Comenzaremos con la instrucción if, que evaluará si una instrucción es verdadera o falsa, y ejecutaremos código solo cuando la instrucción sea verdadera.

      En un editor de texto simple, abra un archivo y escriba el siguiente código:

      grade.go

      package main
      
      import "fmt"
      
      func main() {
          grade := 70
      
          if grade >= 65 {
              fmt.Println("Passing grade")
          }
      }
      

      Con este código, disponemos de la variable grade y le asignaremos el valor entero 70. Luego, usaremos la instrucciónifpara evaluar si la variable “grade” es superior o igual (>=) a 65. Si cumple con esta condición, indicaremos al programa que imprima la cadena Passing grade.

      Guarde el programa como grade.go y ejecútelo en un entorno de programación local desde una ventana de terminal con el comando go run grade.go.

      En este caso, la calificación de 70 cumple la condición de ser superior o igual a 65, por lo que verá el siguiente resultado una vez que ejecute el programa:

      Output

      Passing grade

      A continuación, cambiaremos el resultado de este programa modificando el valor de la variable grade de modo que sea 60:

      grade.go

      package main
      
      import "fmt"
      
      func main() {
          grade := 60
      
          if grade >= 65 {
              fmt.Println("Passing grade")
          }
      }
      

      Cuando guardemos y ejecutemos este código, no veremos resultados porque no se cumplió la condición y no indicamos al programa que ejecute otra instrucción.

      Para dar un ejemplo más, calculemos si el balance de una cuenta bancaria es inferior a 0. Crearemos un archivo llamado account.go y escribiremos el siguiente programa:

      account.go

      package main
      
      import "fmt"
      
      func main() {
          balance := -5
      
          if balance < 0 {
              fmt.Println("Balance is below 0, add funds now or you will be charged a penalty.")
          }
      }
      

      Cuando ejecutemos el programa con go run account.go veremos el siguiente resultado:

      Output

      Balance is below 0, add funds now or you will be charged a penalty.

      En el programa, iniciamos la variable balance con el valor -5, que es inferior a 0. Debido a que el balance cumplió la condición de la instrucción if (balance < 0), una vez que guardemos y ejecutemos el código, recibiremos el resultado de la cadena. Una vez más, si cambiamos el balance a 0 o un número positivo, no veremos resultados.

      Instrucciones Else

      Es probable que le convenga que el programa realice algo aun cuando una instrucción si se evalúe a “false”. En nuestro ejemplo de calificación, nos convendrá obtener resultados independientemente de que la calificación sea o no de aprobación.

      Para hacer esto, agregaremos a la condición de calificación anterior una declaración else que se construye así:

      grade.go

      package main
      
      import "fmt"
      
      func main() {
          grade := 60
      
          if grade >= 65 {
              fmt.Println("Passing grade")
          } else {
              fmt.Println("Failing grade")
          }
      }
      

      Puesto que la variable “grade” tiene el valor 60, la instrucción if se evalúa a “false”, por lo que el programa no imprimirá Passing grade. La instrucción else siguiente indica al programa que realice alguna acción de todos modos.

      Al guardar y ejecutar el programa, veremos el siguiente resultado:

      Output

      Failing grade

      Si luego reescribimos el programa para darle a la calificación el valor 65 o uno superior, en su lugar obtendremos Passing grade.

      Para agregar una instrucción else al ejemplo de cuenta bancaria, reescribimos el código de esta manera:

      account.go

      package main
      
      import "fmt"
      
      func main() {
          balance := 522
      
          if balance < 0 {
              fmt.Println("Balance is below 0, add funds now or you will be charged a penalty.")
          } else {
              fmt.Println("Your balance is 0 or above.")
          }
      }
      

      Output

      Your balance is 0 or above.

      Aquí, cambiamos el valor de la variable balance a un número positivo para que realice una impresión la instrucción else. A fin de lograr que la primera instrucción if realice una impresión, podemos reescribir el valor a un número negativo.

      Al combinar una instrucción if con una instrucción else, construye una instrucción condicional de dos partes que indicará a la computadora que ejecute un código determinado independientemente de que se cumpla o no la condición if.

      Instrucciones else if

      Hasta ahora, presentamos una opción de booleano para declaraciones condicionales y cada declaración if realizando una evaluación a “true” o “false”. En muchos casos, nos convendrá un programa que evalúe más de dos posibles resultados. Para esto, usaremos una instrucción else if, la cual se redacta en Go como else if. else if o la “instrucción else if” se parece a la instrucción if y evaluará otra condición.

      En el programa de cuentas bancarias, posiblemente nos convenga disponer de tres resultados discretos para tres situaciones diferentes:

      • El balance es inferior a 0.
      • El balance es igual a 0.
      • El balance es superior a 0.

      La instrucción else if se dispondrá entre las instrucciones if y else de la siguiente manera:

      account.go

      package main
      
      import "fmt"
      
      func main() {
          balance := 522
      
          if balance < 0 {
              fmt.Println("Balance is below 0, add funds now or you will be charged a penalty.")
          } else if balance == 0 {
              fmt.Println("Balance is equal to 0, add funds soon.")
          } else {
              fmt.Println("Your balance is 0 or above.")
          }
      }
      

      Ahora, hay tres posibles resultados que pueden producirse una vez que ejecutemos el programa:

      • Si la variable balance es igual a 0, veremos el resultado de la instrucción else if (Balance is equal to 0, add funds soon).
      • Si la variable balance se fija en un número positivo, veremos el resultado de la instrucción else (Your balance is 0 or above).
      • Si la variable balance se fija a un número negativo, el resultado será la cadena de la instrucción if (Balance is below 0, add funds now or you will be charged a penalty).

      ¿Qué sucede si, no obstante, deseamos disponer de más de tres posibilidades? Podemos hacer esto escribiendo más de una instrucción else if en nuestro código.

      En el programa grade.go, reescribiremos el código para que haya algunas calificaciones de letras correspondientes a rangos de calificaciones numéricas:

      • 90, o más, equivale a una calificación “A”.
      • Entre 80 y 89, equivale a una calificación “B”.
      • Entre 70 y 79 equivale a una calificación “C”.
      • Entre 65 y 69 equivale a una calificación “D”.
      • 64, o menos, equivale a una calificación “F”.

      Para ejecutar este código, necesitaremos una instrucción if, tres instrucciones else ify una instrucción else que manejarán todos los casos fallidos.

      Reescribiremos el código del ejemplo anterior para disponer de cadenas que impriman cada una de las calificaciones de letras. Podemos hacer que nuestra instrucción else sea igual.

      grade.go

      package main
      
      import "fmt"
      
      func main() {
          grade := 60
      
          if grade >= 90 {
              fmt.Println("A grade")
          } else if grade >= 80 {
              fmt.Println("B grade")
          } else if grade >= 70 {
              fmt.Println("C grade")
          } else if grade >= 65 {
              fmt.Println("D grade")
          } else {
              fmt.Println("Failing grade")
          }
      }
      

      Debido a que las instrucciones else if se evalúan en orden, podemos mantener un perfil bastante básico para nuestras instrucciones. Este programa completa los siguientes pasos:

      1. Si la calificación es superior a 90, el programa imprimirá A grade; si es inferior a 90, el programa continuará con la declaración siguiente…

      2. Si la calificación es superior o igual a 80, el programa imprimirá B grade; si es 79 o inferior, el programa continuará con la declaración siguiente…

      3. Si la calificación es superior o igual a 70, el programa imprimirá C grade; si la calificación es 69 o inferior, el programa continuará con la declaración siguiente…

      4. Si la calificación es superior o igual a 65, el programa imprimirá D grade; si es 64 o inferior, el programa continuará con la declaración siguiente…

      5. El programa imprimirá Failing grade porque no se cumplieron todas las condiciones anteriores.

      Instrucciones If anidadas

      Una vez que se sienta cómodo con las instrucciones if, else if y else, puede proseguir con las instrucciones condicionales anidadas. Podemos usar instrucciones if anidadas para situaciones en las que deseemos verificar una condición secundaria si la primera condición se ejecuta como verdadera. Para esto, podemos tener una instrucción if-else dentro de otra instrucción if-else. Veamos la sintaxis de una instrucción if anidada:

      if statement1 { // outer if statement
          fmt.Println("true")
      
          if nested_statement { // nested if statement
              fmt.Println("yes")
          } else { // nested else statement
              fmt.Println("no")
          }
      
      } else { // outer else statement
          fmt.Println("false")
      }
      

      De este código pueden surgir algunos resultados:

      • Si statement1 se evalúa a “true”, el programa evaluará si nested_statement también se evalúa a “true”. Si ambos casos son verdaderos, se obtendrá el siguiente resultado:

      Output

      true yes
      • Sin embargo, si statement1 se evalúa a “true”, pero nested_statement se evalúa a “false”, el resultado será el siguiente:

      Output

      true no
      • Si statement1 se evalúa a “false”, no se ejecutará la instrucción “if-else” anidada, por lo que la instrucción else se ejecutará sola y el resultado será el siguiente:

      Output

      false

      También podemos disponer de varias instrucciones if anidadas en nuestro código:

      if statement1 { // outer if
          fmt.Println("hello world")
      
          if nested_statement1 { // first nested if
              fmt.Println("yes")
      
          } else if nested_statement2 { // first nested else if
              fmt.Println("maybe")
      
          } else { // first nested else
              fmt.Println("no")
          }
      
      } else if statement2 { // outer else if
          fmt.Println("hello galaxy")
      
          if nested_statement3 { // second nested if
              fmt.Println("yes")
          } else if nested_statement4 { // second nested else if
              fmt.Println("maybe")
          } else { // second nested else
              fmt.Println("no")
          }
      
      } else { // outer else
          statement("hello universe")
      }
      

      En este código, hay una instrucción if anidada dentro de cada instrucción if además de la instrucción if else. Esto hará posibles más opciones dentro de cada condición.

      Veamos un ejemplo de instrucciones if anidadas con nuestro programa de grade.go. Podemos verificar primero si una calificación es de aprobación (superior o igual al 65 %) y luego evaluar la letra de la calificación a la que debería equivaler la calificación numérica. Sin embargo, si la calificación no es de aprobación no es necesario que revisemos las calificaciones con letras y, como alternativa, podemos hacer que el programa informe que la calificación equivale a una desaprobación. Nuestro código modificado con la instrucción if anidada tendrá el siguiente aspecto:

      grade.go

      
      package main
      
      import "fmt"
      
      func main() {
          grade := 92
          if grade >= 65 {
              fmt.Print("Passing grade of: ")
      
              if grade >= 90 {
                  fmt.Println("A")
      
              } else if grade >= 80 {
                  fmt.Println("B")
      
              } else if grade >= 70 {
                  fmt.Println("C")
      
              } else if grade >= 65 {
                  fmt.Println("D")
              }
      
          } else {
              fmt.Println("Failing grade")
          }
      }
      

      Si ejecutamos el código con la variable grade fijada en el valor entero 92, se cumplirá la primera condición y el programa imprimirá Passing grade of: A continuación, verificará si la calificación es mayor o igual a 90, y dado que esta condición también se cumple, imprimirá A.

      Si ejecutamos el código con la variable grade fijada en 60, la primera condición no se cumplirá, por lo que el programa omitirá las instrucciones anidadas if, pasará a la instrucción else e imprimirá Failing grade.

      Podemos, por supuesto,agregar aún más opciones a esto y usar una segunda capa de instrucciones if anidadas. Posiblemente nos convenga evaluar las notas de A+, A y A- por separado. Podemos hacerlo revisando primero si la calificación es de aprobación, luego si la calificación es 90 o superior y finalmente si es superior a 96 para equivaler a A+:

      grade.go

      ...
      if grade >= 65 {
          fmt.Print("Passing grade of: ")
      
          if grade >= 90 {
              if grade > 96 {
                  fmt.Println("A+")
      
              } else if grade > 93 && grade <= 96 {
                  fmt.Println("A")
      
              } else {
                  fmt.Println("A-")
              }
      ...
      

      En este código, para una variable grade fijada en 96 el programa realizará lo siguiente:

      1. Verificar si la calificación es superior o igual a 65 (true)
      2. Imprimir Passing grade of:
      3. Verificar si la calificación es superior o igual a 90 (true)
      4. Verificar si la calificación es superior a 96 (false)
      5. Verificar si la calificación es superior a 93 e inferior o igual a 96 (true)
      6. Imprimir A
      7. Dejar estas instrucciones condicionales anidadas y continuar con el código restante

      Por lo tanto, el resultado del programa para una calificación de 96 tiene el siguiente aspecto:

      Output

      Passing grade of: A

      Las instrucciones if anidadas pueden permitir añadir varios niveles específicos de condiciones a su código.

      Conclusión

      Al usar instrucciones condicionales como if, tendrá mayor control sobre las ejecuciones que realice su programa. Las instrucciones condicionales indican al programa que evalúe si se cumple una condición determinada. Si la condición se cumple, este ejecutará código específico, pero si no se cumple continuará con otros códigos.

      Para continuar practicando con las instrucciones condicionales, intente usar diferentes operadores para familiarizarse más con ellas.



      Source link