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.
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:
Top comments (0)