Me encantó como se explicó cerca del minuto 7:00 lo de los cupos de los canales. ¡Gracias por esmerarte tanto Néstor!
Introducción
Características esenciales de Go
Qué aprenderás y qué necesitas saber
Repaso general: variables, condicionales, slices y map
Repaso general: GoRoutines y apuntadores
Programación orientada a objetos
¿Es Go orientado a objetos?
Structs vs. clases
Métodos y funciones
Constructores
Herencia
Interfaces
Aplicando interfaces con Abstract Factory
Implementación final de Abstract Factory
Funciones anónimas
Funciones variadicas y retornos con nombre
Go Modules
Cómo utilizar los Go modules
Creando nuestro módulo
Testing
Testing
Code coverage
Profiling
Testing usando Mocks
Implementando Mocks
Concurrencia
Unbuffered channels y buffered channels
Waitgroup
Buffered channels como semáforos
Definiendo channels de lectura y escritura
Worker pools
Multiplexación con Select y Case
Proyecto: servidor con worker pools
Definiendo workers, jobs y dispatchers
Creando web server para procesar jobs
Conclusión
Continúa con el Curso de Go Avanzado
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Aportes 15
Preguntas 5
Me encantó como se explicó cerca del minuto 7:00 lo de los cupos de los canales. ¡Gracias por esmerarte tanto Néstor!
Muy buena explicacion por parte del profe, me quedo muy claro 😃
Code with comments:
package main
import (
"fmt"
"sync"
"time"
)
/*
traffic light.
this uses channels and waint groups to 1. execute only 2 doSmth() func
at a time and 2. be able to wait for all of them.
in order of execution it'll:
c := [][] -- two free spaces
c := [routine][] -- one free space
c := [rountine][routine] -- all occupied
c := [][routine] -- one free space
*/
func doSmth(i int, wg *sync.WaitGroup, c chan int) {
defer wg.Done()
fmt.Printf("Id: %d -> started...\n", i)
time.Sleep(time.Second * 4)
fmt.Printf("Id: %d -> finished...\n", i)
<- c // frees the space for new routines
}
func main() {
c := make(chan int, 2) // creates a buffered channel with a capacity of two
var wg sync.WaitGroup // creates wait group
for i := 0; i < 10; i++ {
c <- 1 // alocate a new "instance" in the free space
wg.Add(1) // adds to the wait group
go doSmth(i, &wg, c)
}
wg.Wait()
}
Esto es brutal. Yo desarrollé un integrador que lee datos de Softland ERP y los inserta en Dynamics CRM. Utilicé C#. Resulta que el API de microsoft permite solo 39 llamadas (Creo que eran como 39) después de ahí me daba un error de muchas peticiones el famoso 429. Yo quería que todo fuera rápido. Desarrollé la llamada de cada entidad con task y me las arreglé para hacerlo en pararelo. Pero se fueron toddas las lineas de una sola vez, si habían 100 lineas las 100 intentaban integrarse a la vez, por supuesto, esto provocó que el sistema me obligara a esperar hasta 5 horas, por lo que en lugar de ganar tiempo obtuve un resultado opuesto. Para evitar este problema dividí el total de ejecuciones en paquetes de 20 llamadas, si hay 100 lineas por integrar, tomo 20, las integro y paso a las siguientes 20. Realizar esta segmentación me costó mucho. Tuve que crear un metodo que ahora manejara los task (forma de trabajar concurrencia en c#) y un contador. Con los channels simplemente creo un objeto y lo paso por parámetro. Impresionante. Quiero migrar en go el integrador, es un refactor dificil, no es conveniente. Es un deseo de un junior lo sé, pero como lo deseo!!
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
c := make(chan int, 5)
for i := 0; i < 10; i++ {
wg.Add(1)
c <- 1
go doSomething(i, &wg, c)
}
fmt.Println("Waiting for goroutines to finish")
wg.Wait()
}
func doSomething(i int, wg *sync.WaitGroup, c chan int) {
defer wg.Done()
fmt.Printf("id: %d started \n", i)
time.Sleep(4 * time.Second)
fmt.Printf("id: %d finished \n", i)
<-c
}
Gracias Nestor por la explicación literalmente me abriste la mente.
Que clase tan útil!
Se me hace que este concepto será súper útil al implementar una virtual estate machine (para smart contracts por ejemplo)
Néstor, sos un ckack.
He logrado comprender muchísimas cosas, lo mejor de todo es que con lo visto hasta aquí podré realizar muchas optimizaciones e código muy importante de la empresa.
El concepto de buffered channels como semaforos me parece de bastante utilidad para poder delimitar el consumo de recursos relacionados a las gorutinas que se ejecuten. Excelente explicación! 😄
Excelente explicacion! ahora queda mucho mejor el concepto y uso de canales y waitgroup 😄
La utilidad de los channels como semaforos esta francamente bien y tiene multiples usos. Cada dia me gusta más go
Excelente… Buena clasa, todo muy claro
Justo buscaba algo así para la obtención de datos desde un endpoint que tiene aprox 450 paginas y que se consulta cada 3~4 minutos
Excelente explicacion.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?