#3 - Learning Go - Blocos, Shadowing e Estruturas de controle
Tags: go, beginners, learning, career
Published: 2024-01-12 01:28:56

Nada de especial aqui, anotações pertinentes do capítulo 4 do livro Learning Go - Blocks, Shadows, and Control Structures.

Um comentário especial da minha parte:

Esses conceitos de block e shadowing existem em praticamente todas as linguagens e, embora comum, sempre costumam causar bugs inesperados. A maioria das pessoas acaba comendo bola com closures, shadowing e etc.

Então , meu conselho é prestar bastante atenção nisso e sempre manter o *buffer* das variáveis em contexto hehe.

Seguem as anotações:

## Blocks

Qualquer lugar onde uma declaração de variável pode ocorrer é um bloco.
Tudo que for declarado fora de uma função esta no `package block`.

Os parâmetros e tudo que for definido dentro dos `{}` de uma função estão em um bloco.

Dentro de uma função, todo par de `{}` define um bloco também (estruturas de controle, loop, etc).

Você consegue acessar um identificador definido em blocos de fora em blocos de dentro.

### Shadowing

Ao declarar uma variável em um bloco interno com o mesmo nome de outra variável de um bloco externo estamos fazendo shadowing, ou seja, a variável do bloco externo não é mais acessível e fica “sobreposta” pelo valor da nova variável declarada no bloco interno.

#### Detecção de shadowing

Existe um linter chamado `shadow` que ajuda a detectar shadowing e é muito recomendado que faça parte do seu pipeline de build.

#### Universe Block

Go é uma linguagem enxuta com somente 25 keywords, então algumas palavras que seriam esperadas a serem keywords na verdade acabam sendo identificadores pré declarados, como o caso de tipos built-in (`int` , `string` , etc), constantes (`true` , `false` ), funções (`make` , `close`) e até mesmo `nil` .

Todos esses identificadores são declarados em um bloco que contém todos os outros blocos, que é chamado de `universe block`, devido a isto devemos ter cuidado e não fazer shadowing destes valores. Teríamos comportamentos totalmente inesperados ao redefinir o valor de `true` ou `false` por exemplo.

## If statement

Ifs em Go são basicamente idênticos a outras linguagens, única diferença é que é possível declarar variáveis para uso dentro dos blocos do if else diretamente antes da condição.

## Loops

Em Go, existe somente uma forma de construis loops, sendo o `for` a única keyword pra este fim. Existem algumas formas diferentes de se usar o for em Go.

for-range é a forma utilizada para iterar sobre elementos de tipos built-in (strings, arrays, slices e maps). No for-range podemos ignorar tanto a variável de posição (a primeira na ordem), quanto a variável de valor (ultimo na ordem). Parar ignorar a variável de posição podemos utilizar um `_` como nome da variável, para ignorar a variável de valor podemos simplesmente não declara-la.

### Iterando mapas

É importante destacar que a ordem não é garantida quando iteramos sobre mapas.

### Iterando strings

Na iteração de strings é retornado `runes` em cada iteração, tendo um tratamento especial pra quando um caractere (rune) seja representado por múltiplos bytes. Nesse caso, a variável de posição é incrementada pelo número de bytes que a `rune` possui, a variável de valor assume o valor da representação UTF-8 de 32-bits. Caso não seja possível encontrar uma representação UTF-8 válida, o Unicode replacement character (valor hex 0xfffd) é retornado como valor.

### A variável de valor do for-range é uma cópia

Importante mencionar que a variável de valor do for-range é uma cópia do valor sendo iterado, ou seja, modificar a variável não vai afetar em nada o elemento que esta sob iteração.

### Label em loops

Podemos “nomear” loops para que consigamos utilizar o `break` ou `continue` de loops externos em loops internos.

## Switch

Os `case` são mutuamente exclusivos, ou seja, quando algum case é atingido o switch para.

Existe a keyword `fallthrough` que permite que o switch continue, porém não é muito idiomático utilizá-lo.

### Quando usar if-elses ou switch?

O switch agrupa condicionais relacionadas, ou seja, quando haver uma relação entre as condicionais usar o switch. 

## goto

Evite usar `goto` quase sempre.

Existem alguns poucos casos onde o goto pode simplificar a leitura do código, principalmente quando usamos flags booleanas para controlar o fluxo de alguma forma.

```go
func main() {
	a := rand.Intn(10)
	
	for a < 100 {
		if a%5 == 0 {
			goto done
		}
	
		a=a*2+1
	}

	fmt.Println("do something when the loop completes normally")
done:
    fmt.Println("do complicated stuff no matter why we left the loop")
    fmt.Println(a)
}
```

## Outros capítulos
Esta é uma série onde pretendo fazer anotações de todos os capítulos relevantes do livro Learning Go, seguem os links para os capítulos anteriores e futuros:
[#4 - Learning Go - Funções](https://dev.to/erick_tmr/4-learning-go-funcoes-2n30)
[#2 - Learning Go - Tipos compostos](https://dev.to/erick_tmr/learning-go-tipos-compostos-3f4b)
[#1 - Learning Go - Tipos primitivos e declarações de variáveis](https://dev.to/erick_tmr/learning-go-tipos-primitivos-e-declaracoes-de-variaveis-4b5l)