Golang es un lenguaje de programación concurrente. Tiene características poderosas como y que puede manejar tareas asincrónicas muy bien. Además, las goroutines no son subprocesos del sistema operativo, y es por eso que puede activar tantas goroutines como desee sin mucha sobrecarga, su tamaño de pila comienza en solo 2 . Entonces por qué ? Async/Await es una buena función de lenguaje que proporciona una interfaz más sencilla para la programación asíncrona. Goroutines Channels KB async/await Enlace del proyecto: https://github.com/Joker666/AsyncGoDemo ¿Como funciona? Comenzó con F# y luego C#, ahora en Python y Javascript, async/await es una característica extremadamente popular de un lenguaje. Simplifica la estructura de ejecución del método asíncrono y se lee como código síncrono. Mucho más fácil de seguir para los desarrolladores. Veamos un ejemplo simple en C# de cómo funciona async/await Task Main(string[] args) { Console.WriteLine( ); done = DoneAsync(); Console.WriteLine( ); Console.WriteLine( done); } Task<int> DoneAsync() { Console.WriteLine( ); Task.Delay( ); Console.WriteLine( ); ; } static async "Let's start ..." var "Done is running ..." await static async "Warming up ..." await 3000 "Done ..." return 1 tenemos el función que se ejecutaría cuando se ejecute el programa. Tenemos que es una función asíncrona. Detenemos la ejecución del código con función durante 3 segundos. Delay es una función asíncrona en sí misma, por lo que la llamamos con await. Main DoneAsync Delay await solo bloquea la ejecución del código dentro de la función asíncrona En la función principal, no llamamos con espera. Pero la ejecución comienza para . Solo cuando lo esperamos, recuperamos el resultado. El flujo de ejecución se ve así DoneAsync DoneAsync Let 's start ... Warming up ... Done is running ... Done ... 1 Esto parece increíblemente simple para la ejecución asíncrona. Veamos cómo podemos hacerlo con Golang usando Goroutines y Channels { r := ( ) fmt.Println( ) { time.Sleep( * time.Second) r <- fmt.Println( ) }() r } { fmt.Println( ) val := DoneAsync() fmt.Println( ) fmt.Println(<- val) } func DoneAsync () chan int make chan int "Warming up ..." go func () 3 1 "Done ..." return func main () "Let's start ..." "Done is running ..." Aquí, se ejecuta de forma asíncrona y devuelve un canal. Escribe un valor en el canal una vez que termina de ejecutar la tarea asíncrona. En función, invocamos y seguimos haciendo nuestras operaciones y luego leemos el valor del canal devuelto. Es una llamada de bloqueo que espera hasta que el valor se escribe en el canal y después de que obtiene el valor lo escribe en la consola. DoneAsync main DoneAsync Let 's start ... Warming up ... Done is running ... Done ... 1 Vemos, logramos el mismo resultado que el programa C# pero no se ve tan elegante como async/await. Si bien esto es realmente bueno, podemos hacer muchas cosas más granulares con este enfoque con mucha facilidad, también podemos implementar palabras clave asíncronas/en espera en Golang con una estructura y una interfaz simples. Probemos eso. Implementando Async/Await El código completo está disponible en el enlace del proyecto. Para implementar async/await en Golang, comenzaremos con un directorio de paquetes llamado . La estructura del proyecto parece async . ├── async │ └── async ├── main └── README.md .go .go En el archivo asíncrono, escribimos la interfaz futura más simple que puede manejar tareas asíncronas. async Future { Await() {} } future { await {} } {} { f.await(context.Background()) } {}) Future { result {} c := ( {}) { (c) result = f() }() future{ await: {} { { <-ctx.Done(): ctx.Err() <-c: result } }, } } package import "context" // Future interface has the method signature for await type interface interface type struct func (ctx context.Context) interface func (f future) Await () interface return // Exec executes the async function func Exec (f () func interface var interface make chan struct go func () defer close return func (ctx context.Context) interface select case return case return No está sucediendo mucho aquí, agregamos un interfaz que tiene la firma del método. A continuación, agregamos un estructura que contiene un valor, una firma de función de la función. Ahora implementos de estructura el método Await de la interfaz invocando su propio función. Future Await future await futute Future await A continuación en el función, ejecutamos la función pasada de forma asíncrona en goroutine. Y le devolvemos el función. Espera a que el canal se cierre o el contexto para leer. Según lo que suceda primero, devuelve el error o el resultado, que es una interfaz. Exec await Ahora armado con este nuevo paquete asíncrono, veamos cómo podemos cambiar nuestro código go actual { fmt.Println( ) time.Sleep( * time.Second) fmt.Println( ) } { fmt.Println( ) future := async.Exec( {} { DoneAsync() }) fmt.Println( ) val := future.Await() fmt.Println(val) } func DoneAsync () int "Warming up ..." 3 "Done ..." return 1 func main () "Let's start ..." func () interface return "Done is running ..." A primera vista, parece mucho más limpio, no estamos trabajando explícitamente con goroutine o canales aquí. Nuestro La función ha sido cambiada a una naturaleza completamente síncrona. En la función principal, usamos el paquete método para manejar . que inicia la ejecución de . El flujo de control se devuelve a función que puede ejecutar otras piezas de código. Finalmente, hacemos una llamada de bloqueo a y volver a leer los datos. DoneAsync async Exec DoneAsync DoneAsync main Await Ahora el código se ve mucho más simple y fácil de leer. Podemos modificar nuestro paquete asíncrono para incorporar muchos otros tipos de tareas asíncronas en Golang, pero por ahora nos limitaremos a una implementación simple en este tutorial. Conclusión Hemos revisado qué async/await it e implementamos una versión simple de eso en Golang. Le animo a que busque mucho más en async/await y vea cómo puede facilitar la legibilidad del código base mucho mejor.