-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #50 from fabianoflorentino/5-terminar-o-curso
5 terminar o curso
- Loading branch information
Showing
8 changed files
with
369 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
--- | ||
description: | ||
name: "Capítulo 21: Canais" | ||
sections: | ||
- title: Entendendo Canais | ||
text: | | ||
- Canais são o Jeito Certo® de fazer sincronização e código concorrente. | ||
- Eles nos permitem trasmitir valores entre goroutines. | ||
- Servem pra coordenar, sincronizar, orquestrar, e buffering. | ||
- Na prática: | ||
- make(chan type, b) | ||
- <- 42 | ||
- <-c | ||
- Canais bloqueiam: | ||
- Eles são como corredores em uma corrida de revezamento | ||
- Eles tem que "passar o bastão" de maneira sincronizada | ||
- Se um corredor tentar passar o bastão pro próximo, mas o próximo corredor não estiver lá... | ||
- Ou se um corredor ficar esperando receber o bastão, mas ninguem entregar... | ||
- ...não dá certo. | ||
- Exemplos: | ||
- Poe um valor num canal e faz um print. Block. | ||
- Código acima com goroutine. | ||
- Ou com buffer. Via de regra: má idéia; é legal em certas situações, mas em geral é melhor sempre passar o bastão de maneira sincronizada. | ||
- Interessante: ref/spec → types | ||
- Código: | ||
- Block: https://play.golang.org/p/dClS7vQlYE (não roda!) | ||
- Go routine: https://play.golang.org/p/ZbNCwUuiPi | ||
- Buffer: https://play.golang.org/p/32vYvCR7qn | ||
- Buffer block: https://play.golang.org/p/smeW6vigAT | ||
- Mais buffer: https://play.golang.org/p/Pe2pcboGiA | ||
- title: Canais direcionais & utilizando canais | ||
text: | | ||
- Canais podem ser direcionais. | ||
- E isso serve pra...? | ||
- Um send channel e um receive channel são tipos diferentes. Isso permite que os type-checking mechanisms do compilador façam com que não seja possível, por exemplo, escrever num canal de leitura. | ||
- Aos aventureitos: https://stackoverflow.com/questions/13596186/whats-the-point-of-one-way-channels-in-go | ||
- Canais bidirecionals (send & receive) | ||
- send chan<- | ||
- error: "invalid operation: <-cs (receive from send-only type chan<- int)" | ||
- receive <-chan | ||
- error: "invalid operation: cr <- 42 (send to receive-only type <-chan int)" | ||
- Exemplo: https://play.golang.org/p/TlcSm8bHkW | ||
- A seta sempre aponta para a esquerda. | ||
- Assignment/conversion: | ||
- de geral para específico | ||
- de específico para geral não | ||
- Exemplos: | ||
- geral pra específico: https://play.golang.org/p/H1uk4YGMBB | ||
- específico pra específico: https://play.golang.org/p/8JkOnEi7-a | ||
- específico pra geral: https://play.golang.org/p/4sOKuQRHq7 | ||
- atribuição tipos !=: https://play.golang.org/p/bG7H6l03VQ | ||
- Em funcs podemos especificar: | ||
- receive channel | ||
- Parâmetro receive channel: (c <-chan int) | ||
- No scope dessa função, esse canal só recebe | ||
- Não podemos fechar um receive channel | ||
- send channel | ||
- Parâmetro send channel: (c chan<- int) | ||
- No scope dessa função, esse canal só envia | ||
- Podemos fechar um send channel | ||
- Exemplo: passando informação de uma função para outra. | ||
- Código: https://play.golang.org/p/TlcSm8bHkW (replay) | ||
- title: Range e Close | ||
text: | | ||
- Range: | ||
- gofunc com for loop com send e close(chan) | ||
- recebe com range chan | ||
- Código: https://play.golang.org/p/_g5IEjSkh1 | ||
- title: Select | ||
text: | | ||
- Select é como switch, só que pra canais, e não é sequencial. | ||
- "A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready." — https://tour.golang.org/concurrency/5 | ||
- Na prática: | ||
- Exemplo 1: | ||
- Duas go funcs enviando X/2 numeros cada uma pra um canal | ||
- For loop X valores, select case <-x | ||
- Exemplo 2: | ||
- Func 1 recebe X valores de canal, depois manda qualquer coisa pra chan quit | ||
- Func 2 for infinito, select: case envia pra canal, case recebe de quit | ||
- Exemplo 3: | ||
- Chans par, ímpar, quit | ||
- Func send manda números pares pra um canal, ímpares pra outro, e fecha/quit | ||
- Func receive é um select entre os três canais, encerra no quit | ||
- Problema! | ||
- Go Playground: | ||
- 1. https://play.golang.org/p/xC3e1wBxgv | ||
- 2. https://play.golang.org/p/_NZqhBXN-v | ||
- 3. https://play.golang.org/p/rK8QwsBo0H | ||
- title: A expressão comma ok | ||
text: | | ||
- v, ok := <-chan | ||
- Se receber valor: v, true | ||
- Canal fechado, nada, etc.: zero v, false | ||
- Agora vamos resolver o problema do exercício anterior usando comma ok. | ||
- Código: https://github.com/ellenkorbes/aprendago/blob/master/c%C3%B3digo/21_canais/06_exerc%C3%ADcio_anterior/main.go | ||
- title: Convergência | ||
text: | | ||
- Observamos convergência quando informação de vários canais é enviada a um número menor de canais. | ||
- Interessante: <- <- | ||
- Na prática, exemplos: | ||
- 1. Todd: | ||
- Canais par, ímpar, e converge. | ||
- Func send manda pares pra um, ímpares pro outro, depois fecha. | ||
- Func receive cria duas go funcs, cada uma com um for range, enviando dados dos canais par e ímpar pro canal converge. Não esquecer de WGs! | ||
- Por fim um range retira todas as informações do canal converge. | ||
- 2. Rob Pike (palestra Go Concurrency Patterns): | ||
- Func trabalho cria um canal, cria uma go func que manda dados pra esse canal, e retorna o canal. Interessante: time.Duration(rand.Intn(1e3)) | ||
- Func converge toma dois canais, cria um canal novo, e cria duas go funcs com for infinito que passa tudo para o canal novo. Retorna o canal novo. | ||
- Por fim chamamos canal := converge(trabalho(nome1), trabalho(nome2)) e usamos um for para receber dados do canal var. | ||
- Código: https://github.com/ellenkorbes/aprendago/tree/master/c%C3%B3digo/21_canais/07 | ||
- title: Divergência | ||
text: | | ||
- Divergência é o contrário de convergência :) | ||
- Na prática, exemplos: | ||
- 1. Um stream vira centenas de go funcs que depois convergem. | ||
- Dois canais. | ||
- Uma func manda X números ao primeiro canal. | ||
- Outra func faz um range deste canal, e para cada ítem lança uma go func que poe o retorno de trabalho() no canal dois. | ||
- Trabalho() é um timer aleatório pra simular workload. | ||
- Por fim, range canal dois demonstra os valores. | ||
- 2. Com throttling! Ou seja, com um número máximo de go funcs. | ||
- Ídem acima, mas a func que lança go funcs é assim: | ||
- Cria X go funcs, cada uma com um range no primeiro canal que, para cada item, poe o retorno de trabalho() no canal dois. | ||
- Código: https://github.com/ellenkorbes/aprendago/tree/master/c%C3%B3digo/21_canais/08 | ||
- title: Context | ||
text: | | ||
- Só pra ter uma idéia geral: | ||
- Se a gente lança 500 goroutines pra fazer uma tarefa, e cancelamos a tarefa no meio do caminho, como fazemos pra matar as goroutines? | ||
- Documentação: https://golang.org/pkg/context/ | ||
- Aos aventureiros: https://blog.golang.org/context | ||
- Destaques: | ||
- ctx := context.Background | ||
- ctx, cancel = context.WithCancel(context.Background) | ||
- goroutine: select case <-ctx.Done(): return; default: continua trabalhando. | ||
- check ctx.Err(); | ||
- Tambem tem WithDeadline/Timeout | ||
- Exemplos (Todd): | ||
- Analisando: | ||
- Background: https://play.golang.org/p/cByXyrxXUf | ||
- WithCancel: https://play.golang.org/p/XOknf0aSpx | ||
- Função Cancel: https://play.golang.org/p/UzQxxhn_fm | ||
- Exemplos práticos: | ||
- func WithCancel: https://play.golang.org/p/Lmbyn7bO7e | ||
- func WithCancel: https://play.golang.org/p/wvGmvMzIMW | ||
- func WithDeadline: https://play.golang.org/p/Q6mVdQqYTt | ||
- func WithTimeout: https://play.golang.org/p/OuES9sP_yX | ||
- func WithValue: https://play.golang.org/p/8JDCGk1K4P |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Package canais provides functions to demonstrate and execute various concepts related to channels in Go. | ||
// It includes sections on understanding channels, directional channels, range and close, select statement, | ||
// comma ok idiom, convergence, divergence, and context. The package also provides menu options and help | ||
// descriptions for each section. | ||
package canais | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/fabianoflorentino/aprendago/pkg/format" | ||
) | ||
|
||
// rootDir is a constant that holds the relative path to the "canais" directory | ||
// within the "internal" directory. This path is used as a base directory for | ||
// various operations related to the "canais" module in the project. | ||
const ( | ||
rootDir = "internal/canais" | ||
) | ||
|
||
// Canais is a function that prints the title of Chapter 21: Channels | ||
// and executes several sections related to the topic of channels in Go. | ||
// The sections covered are: | ||
// - Understanding Channels | ||
// - Directional Channels & Using Channels | ||
// - Range and Close | ||
// - Select | ||
// - The comma ok idiom | ||
// - Convergence | ||
// - Divergence | ||
// - Context | ||
func Canais() { | ||
fmt.Printf("\n\nCapítulo 21: Canais\n") | ||
|
||
executeSection("Entendendo Canais") | ||
executeSection("Canais direcionais & utilizando canais") | ||
executeSection("Range e Close") | ||
executeSection("Select") | ||
executeSection("A expressão comma ok") | ||
executeSection("Convergência") | ||
executeSection("Divergência") | ||
executeSection("Context") | ||
} | ||
|
||
// MenuCanais returns a slice of format.MenuOptions, each representing a menu option | ||
// for different topics related to Go channels. Each menu option includes a string | ||
// that represents the option and a function to execute when the option is selected. | ||
// The topics covered include understanding channels, directional channels, range and close, | ||
// select statement, the comma ok expression, convergence, divergence, and context. | ||
func MenuCanais([]string) []format.MenuOptions { | ||
return []format.MenuOptions{ | ||
{Options: "--entendendo-canais", ExecFunc: func() { executeSection("Entendendo Canais") }}, | ||
{Options: "--canais-direcionais-utilizando-canais", ExecFunc: func() { executeSection("Canais direcionais & utilizando canais") }}, | ||
{Options: "--range-e-close", ExecFunc: func() { executeSection("Range e Close") }}, | ||
{Options: "--select", ExecFunc: func() { executeSection("Select") }}, | ||
{Options: "--a-expressao-comma-ok", ExecFunc: func() { executeSection("A expressão comma ok") }}, | ||
{Options: "--convergencia", ExecFunc: func() { executeSection("Convergência") }}, | ||
{Options: "--divergencia", ExecFunc: func() { executeSection("Divergência") }}, | ||
{Options: "--context", ExecFunc: func() { executeSection("Context") }}, | ||
} | ||
} | ||
|
||
// HelpMeCanais prints a list of topics related to channels in Go. | ||
// It creates a slice of HelpMe structs, each containing a flag and a description | ||
// of a specific topic about channels. The topics include understanding channels, | ||
// directional channels, using channels, range and close, select statement, | ||
// the comma ok idiom, convergence, divergence, and context. | ||
// The function then prints the chapter title and calls PrintHelpMe to display the topics. | ||
func HelpMeCanais() { | ||
hlp := []format.HelpMe{ | ||
{Flag: "--entendendo-canais", Description: "Entendendo Canais"}, | ||
{Flag: "--canais-direcionais-utilizando-canais", Description: "Canais direcionais & utilizando canais"}, | ||
{Flag: "--range-e-close", Description: "Range e Close"}, | ||
{Flag: "--select", Description: "Select"}, | ||
{Flag: "--a-expressao-comma-ok", Description: "A expressão comma ok"}, | ||
{Flag: "--convergencia", Description: "Convergência"}, | ||
{Flag: "--divergencia", Description: "Divergência"}, | ||
{Flag: "--context", Description: "Context"}, | ||
} | ||
|
||
fmt.Println("\nCapítulo 21: Canais") | ||
format.PrintHelpMe(hlp) | ||
} | ||
|
||
// executeSection formats and processes a given section of the project. | ||
// It takes a section name as a string parameter and uses the FormatSection | ||
// function from the format package to apply formatting to the specified section | ||
// within the root directory. | ||
func executeSection(section string) { | ||
format.FormatSection(rootDir, section) | ||
} |
Oops, something went wrong.