Hola mundo en Go

1

Introducción al Curso de Golang

2

¿Qué es, por qué y quienes utilizan Go?

3

Instalar Go en Linux

4

Instalar Go en Mac

5

Instalar Go en Windows

6

Nuestras primeras líneas de código con Go

Variables, funciones y documentación

7

Variables, constantes y zero values

8

Operadores aritméticos

9

Tipos de datos primitivos

10

Paquete fmt: algo más que imprimir en consola

11

Uso de funciones

12

Go doc: La forma de ver documentación

Estructuras de control de flujo y condicionales

13

El poder de los ciclos en Golang: for, for while y for forever

14

Operadores lógicos y de comparación

15

El condicional if

16

Múltiple condiciones anidadas con Switch

17

El uso de los keywords defer, break y continue

Estructuras de datos básicas

18

Arrays y Slices

19

Recorrido de Slices con Range

20

Llave valor con Maps

21

Structs: La forma de hacer clases en Go

22

Modificadores de acceso en funciones y Structs

Métodos e interfaces

23

Structs y Punteros

24

Stringers: personalizar el output de Structs

25

Interfaces y listas de interfaces

Concurrencia y Channels

26

¿Qué es la concurrencia?

27

Primer contacto con las Goroutines

28

Channels: La forma de organizar las goroutines

29

Range, Close y Select en channels

Manejo de paquetes y Go Modules

30

Go get: El manejador de paquetes

31

Go modules: Ir más allá del GoPath con Echo

32

Modificando módulos con Go

Despedida del curso

33

Despedida

Bonus

34

Cheat Sheet Go

35

Librerías para desarrollo web con Go

36

Data Science con Go

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Primer contacto con las Goroutines

27/36
Recursos

Aportes 15

Preguntas 5

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Tuve que ver un par de veces la clase para entender, aquí comparto el código con comentarios con la finalidad de que quede un poco mas claro el tema 😃 espero les sea de ayuda.

Peguen el codigo en VSCode para una mejor legibilidad jeje

package main

import (
	"fmt"
	"sync"
	"time"
)

func say(text string, wg *sync.WaitGroup) { // Gorutine

	defer wg.Done() // Esta linea se va a ejecutar hasta el final de la funcion, y de esta forma libera el gorutine del WaitGroup

	fmt.Println(text)
}

func main22() {

	var wg sync.WaitGroup // El paquete sync permite interacturar de forma primitiva con las gorutine. Variable que acomula un conjunto de gorutines y los va liberando poco a poco

	fmt.Println("Hello")

	wg.Add(1) // Indicamos que vamos a agregar 1 Gorutine al WaitGroup para que espere su ejecucion antes de que la gurutine base (main) muera, y así le de tiempo a la siguiente gorutine de ejecutarse

	go say("world", &wg) // la palabra reservada go ejecutará la funcion de forma concurrente

	wg.Wait() // Funcion del WaitGroup que sirve para decirle al gorutine principal (main) que espere hasta que todas las gorutine del WaitGroup finalicen, es decir, hasta que se ejecute 'defer wg.Done()' en cada una de las goroutines

	go func(text string) { // Funciona anonima
		fmt.Println(text)
	}("Adios")

	time.Sleep(time.Second * 1) // ! Funcion para que cuando llegue a esta linea espere el tiempo indicado (lo suficiente para que la Gorutine ejecute su funcion de forma concurrente)

	// Nota: Para fines practicos se hace uso de la funcion Sleep(), pero en realidad NO es una buena practica, es mejor utilizar los WaitGroups

}

Me costó un poco de trabajo entender esta clase. Así que aquí va mi aporte:

Un WaitGroup espera a que una colección de goroutines termine su ejecución.
Para esto se una la WaitGroup.Add() ( wg.add(1) en el ejemplo de la clase).
El número entero indica el número de goroutines que debe esperar para finalizar la ejecución de la goroutine principal.

Cada vez que una goroutine termina su ejecución, llama el método Done(). Esto hace que el contador del WaitGroup se reduzca.
Cuando el contador llegue a zero la rutina principal continuará su ejecución.

La función wait() bloquea la rutina principal hasta que todas las demás rutinas del grupo hayan terminado.

Hilos (Concurrencia)

💡 La concurrencia es un paradigma que indica la manera de ejecución de algunos procesos.

.
Podemos denotar 2 aspectos importantes en este tema:

  • Sincronizmo: Ejecución secuencial bloqueable.
  • Asíncronizmo: Ejecución paralela de procesos

.
En este punto, JavaScript se ve vulnerable porque la concurrencia no es uno de sus fuertes y por ello, pudiera romper el concepto a algunos.
.

Definición

💡 Un hilo, es una línea de ejecución de algún proceso que fundamentalmente no es ni sincrónico, ni asincrónico.

.
Mencionamos que la concurrencia es un paradigma ya que nos permite realizar procesos delegados según sea SO, su peso o prioridad.

.
Les dejo un ejemplo para que evalúen la concurrencia desde otro enfoque.

No agregaste un wg.Add(1) para la función anónima. Esto quiere decir que si usamos Gorutines con funciones anónimas no es necesario hacer uso de WaitGroup?

Es algo muy muy similar al asincronismo en JavaScript
[https://www.youtube.com/watch?v=bWvnWhVCHAc]( Asincronismo Platzi – Freddy Vega)

🤯

Mi ejercicio para practicar

package main

import (
	"fmt"
	"sync"
)

func mostrar(a int, wg *sync.WaitGroup) {
	fmt.Println(a)
	wg.Done()

}

func main() {
	var slice = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	var wg sync.WaitGroup
	wg.Add(len(slice))

	for i := range slice {
		go mostrar(i, &wg)
	}

	wg.Wait()
}

package main

import (
	"fmt"
	"sync"
	"time"
)


func say(text string, wg *sync.WaitGroup) {
	defer wg.Done()
	fmt.Println(text)
}

func main() {

	var wg sync.WaitGroup

	fmt.Println("Hello")

	wg.Add(2)
	go say("world", &wg)
	go say("!", &wg)
	
	wg.Wait()
	
	go func(text string) {
		fmt.Println(text)
	}("Adios")

	time.Sleep(time.Second * 1)
}

En mis palabras, concurrencia y paralelismo. Espero que les sea de ayuda.

La concurrencia es el conjunto de mecanismos por los cuales podemos correr varios procesos o hilos de ejecución al mismo tiempo. Por ejemplo, tener varios núcleos en el procesador y que cada uno se encargue de un proceso, o dando un cachito de tiempo a cada proceso de forma intercalada (multiplexación en el tiempo). Incluso, podemos pensar la concurrencia a nivel de un conjunto de máquinas, cada una ejecutando programas diferentes que se comunican entre sí.

El paralelismo, por otro lado, es dividir un problema en varias partes y resolver cada una en simultáneo. Al final, podemos usar cada uno de los resultados para crear una solución al problema original (forkJoin).

Si encuentran alguna mejora, háganme saber.

MI Codigo comentado.

package main

import (
	"fmt"
	"sync"
	"time"
)

func say(text string, wq *sync.WaitGroup) {
	defer wq.Done()
	fmt.Println(text)
}
func main() {
	//sync.WaitGroup nos permitira agrupar las GoRutines y les difinira un tiempo determinado dentro de el hilo del nucleo como concurrencia.
	var wq sync.WaitGroup

	fmt.Println("Hello")
	//Se anexa la informacion de las GoRutines que se agruparan junto con la GoRutine Main.
	wq.Add(1)

	//El tiempo de la ejecucion de una GoRutine Adicional se tomara como un tiempo extra, que la funcion main no esperara.
	go say("World", &wq)
	//Justo despues de que se este ejecutando la funcion say, la funcion main estara sobre la linea de codigo 24.
	wq.Wait()
	//con este atributo le diremos a la funcion main que espere, hasta que el atributo .Done(Linea 10) en la funcion ejecutada en una GoRutine adicional,se ejecute.
	//Una vez ejecutada, la funcion main finalizara.
	fmt.Println("Ha finalizado. :)")

	// Tambien Podremos ejecutar dentro de una GoRutine adicional, funciones anonimas.
	go func(text string) {
		fmt.Println(text)
	}(":) ahora sí, adios.")
	//Este time.sleep le esta dando tiempo a que la GoRutine adicional, que contine la funcion anonima, se ejecute.
	time.Sleep(time.Second * 1)

}

:3
Brutal.

Este es un tema algo confuso, hice una versión un poco más resumida del código de la clase, espero que les sirva! c:

func main() {

	// Creamos un WaitGroup de esta forma
	var waitGroup sync.WaitGroup

	// Imprimimos en el runtime de main
	fmt.Println("Hola")

	// Indicamos al WG que agregaremos una rutina 
	// (incrementa el contador interno del WG en 1)
	waitGroup.Add(1)

	// Imprimimos usando una go routine, pasando el 
	// pointer al WG como argumento dentro de una función
	// anónima. Se recomienda siempre usar funciones al
	// implementar un WG. El keyword "go" indica la línea
	// que se ejecutará de forma concurrente usando Go Routines
	go func (text string, localWG *sync.WaitGroup) {
		
		// Esto indica que la Go routine ha terminado y
		// reduce el contador interno del WG en 1. Usamos defer
		// para que se ejecute al final de la ejecución de la 
		// función anónima
		defer localWG.Done()
		fmt.Println(text)
	}("mundo", &waitGroup)
	
	// Por último, antes que finalice main, usamos el WG para
	// indicarle a Go que debe esperar a que todas las rutinas
	// terminen. Es decir, que el contador interno regrese a 0.
	waitGroup.Wait()
}

Interesante

El asincronismo esta conquistando el mundo.