Para implementar la concurrencia en Go, debemos anteponer a una línea de código la palabra go

package main

import "fmt"

func say(text string) {
	fmt.Println(text)
}

func main(){
	say("Hello")
	go say("World")
}

Pero este código solo va a imprimir "Hello" , y es porque la función main se ejecuta en un goroutine, y go say("World") se ejecuta en otro goroutine, pero cuando termina say("Hello")termina el goroutine y no deja ejecutar otro.

Esto lo podemos solucionar (de una manera no muy recomendada), ejecuando un time.Sleep dentro de la función main para que pueda ejecutarse el goroutine go say("World").

package main

import (
	"fmt"
	"time"
)

func say(text string) {
	fmt.Println(text)
}

func main(){
	say("Hello")
	go say("World")

	time.Sleep(time.Second + 1)
}

De este modo imprime ambas palabras. Pero esto no es eficiente para el código, una mejor forma es hacer lo siguiente:

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 main() {

	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

}

Pero usualmente no se utilizan los sync.WaitGroup porque su complejidad, aunque es más eficiente. En su lugar se utilizan los channels que se verán en la próxima clase.

Funciones anónimas

Las goroutines se suelen utilizar mucho con funciones anónimas, y son funciones que no son declaradas anteriormente sino que se realiza dentro de otra función y tiene su vida dentro de ella misma.

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