Como Usar Variáveis e Constantes em Go

Variáveis são um conceito importante de programação a ser dominado. São símbolos que representam um valor que você está usando em um programa.

Este tutorial abordará alguns conceitos básicos de variáveis e as melhores práticas para usá-las nos programas Go que você criar.

Entendendo Variáveis

Em termos técnicos, uma variável é a atribuição de uma localização de armazenamento a um valor que está associado a um nome simbólico ou identificador. Usamos o nome da variável para referenciar esse valor armazenado dentro de um programa de computador.

Podemos pensar em uma variável como um rótulo com um nome, que você amarra a um valor.

Digamos que temos um inteiro, 1032049348, e queremos armazená-lo em uma variável em vez de digitar repetidamente o longo número. Para fazer isso, podemos usar um nome fácil de lembrar, como a variável i. Para armazenar um valor em uma variável, usamos a seguinte sintaxe:

i := 1032049348

Podemos pensar nesta variável como um rótulo que está amarrado ao valor.

O rótulo tem o nome da variável i escrito nele e está amarrado ao valor inteiro 1032049348.

A frase i := 1032049348 é uma declaração e atribuição que consiste em algumas partes:

  • o nome da variável (i)
  • a atribuição de declaração curta (:=)
  • o valor que está sendo atribuído ao nome da variável (1032049348)
  • o tipo de dado inferido pelo Go (int)

Veremos mais adiante como definir explicitamente o tipo na próxima seção.

Juntos, essas partes compõem a instrução que define a variável i como igual ao valor do inteiro 1032049348.

Assim que definimos uma variável como igual a um valor, inicializamos ou criamos essa variável. Uma vez feito isso, estamos prontos para usar a variável em vez do valor.

Uma vez que definimos i como igual ao valor de 1032049348, podemos usar i no lugar do inteiro, então vamos imprimi-lo:

package main

import "fmt"

func main() {
	i := 1032049348
	fmt.Println(i)
}
Output
1032049348

Também podemos fazer matemática de forma rápida e fácil usando variáveis. Com i := 1032049348, podemos subtrair o valor inteiro 813 com a seguinte sintaxe:

fmt.Println(i - 813)
Output
1032048535

Neste exemplo, o Go faz a matemática para nós, subtraindo 813 da variável i para retornar a soma 1032048535.

Falando em matemática, variáveis podem ser definidas como igual ao resultado de uma equação matemática. Você também pode somar dois números e armazenar o valor da soma na variável x:

x := 76 + 145

Você deve ter notado que este exemplo se parece com álgebra. Da mesma forma que usamos letras e outros símbolos para representar números e quantidades dentro de fórmulas e equações, variáveis são nomes simbólicos que representam o valor de um tipo de dado. Para a sintaxe correta do Go, você precisará garantir que sua variável esteja do lado esquerdo de quaisquer equações.

Vamos em frente e imprimir x:

package main

import "fmt"

func main() {
	x := 76 + 145
	fmt.Println(x)
}
Output
221

Go retornou o valor 221 porque a variável x foi definida como a soma de 76 e 145.

Variáveis podem representar qualquer tipo de dado, não apenas inteiros:

s := "Hello, World!"
f := 45.06
b := 5 > 9 // Um valor booleano retornará verdadeiro ou falso
array := [4]string{"item_1", "item_2", "item_3", "item_4"}
slice := []string{"one", "two", "three"}
m := map[string]string{"letter": "g", "number": "seven", "symbol": "&"}

Se você imprimir qualquer uma dessas variáveis, Go retornará o que essa variável é equivalente. Vamos trabalhar com a declaração de atribuição para o tipo de dado slice de strings:

package main

import "fmt"

func main() {
	slice := []string{"one", "two", "three"}
	fmt.Println(slice)
}
Output
[one two three]

Atribuímos o valor de []string{"one", "two", "three"} à variável slice e, em seguida, usamos a função fmt.Println para imprimir esse valor chamando slice.

Variáveis funcionam ao alocar uma pequena área de memória no seu computador que aceita valores especificados que são então associados a esse espaço.

Declarando Variáveis

Em Go, existem várias maneiras de declarar uma variável, e em alguns casos, mais de uma maneira de declarar exatamente a mesma variável e valor.

Podemos declarar uma variável chamada i do tipo de dado int sem inicialização. Isso significa que declararemos um espaço para colocar um valor, mas não daremos a ele um valor inicial:

var i int

Isso cria uma variável declarada como i do tipo de dado int.

Podemos inicializar o valor usando o operador de igualdade (=), como no exemplo a seguir:

var i int = 1

Em Go, ambas as formas de declaração são chamadas de declarações longas de variáveis.

Também podemos usar a declaração curta de variável:

i := 1

Neste caso, temos uma variável chamada i e um tipo de dado int. Quando não especificamos um tipo de dado, Go inferirá o tipo.

Com as três maneiras de declarar variáveis, a comunidade Go adotou as seguintes convenções:

  • Use a forma longa, var i int, apenas quando não estiver inicializando a variável.

  • Use a forma curta, i := 1, ao declarar e inicializar.

  • Se você não deseja que Go infira o tipo de dado, mas ainda quer usar a declaração curta de variável, pode encapsular o valor no tipo desejado com a seguinte sintaxe:

i := int64(1)

Não é considerado idiomático em Go usar a forma longa de declaração de variável quando estamos inicializando o valor:

var i int = 1

É uma boa prática seguir como a comunidade Go normalmente declara variáveis para que outros possam ler seus programas sem problemas.

Valores Zero

Todos os tipos incorporados têm um valor zero. Qualquer variável alocada é utilizável mesmo que nunca tenha um valor atribuído. Podemos ver os valores zero para os seguintes tipos:

package main

import "fmt"

func main() {
	var a int
	var b string
	var c float64
	var d bool

	fmt.Printf("var a %T = %+v\n", a, a)
	fmt.Printf("var b %T = %q\n", b, b)
	fmt.Printf("var c %T = %+v\n", c, c)
	fmt.Printf("var d %T = %+v\n\n", d, d)
}
Output
var a int = 0 var b string = "" var c float64 = 0 var d bool = false

Utilizamos o verbo %T na instrução fmt.Printf. Isto informa à função para imprimir o tipo de dado da variável.

Em Go, como todos os valores têm um valor zero, não podemos ter valores indefinidos como em algumas outras linguagens. Por exemplo, um booleano em algumas linguagens poderia ser indefinido, verdadeiro ou falso, o que permite três estados para a variável. Em Go, não podemos ter mais de dois estados para um valor booleano.

Nomeação de Variáveis: Regras e Estilo

A nomeação de variáveis é bastante flexível, mas há algumas regras a ter em mente:

  • Os nomes das variáveis devem ser apenas uma palavra (sem espaços).
  • Os nomes das variáveis devem ser compostos apenas por letras, números e sublinhados (_).
  • Os nomes das variáveis não podem começar com um número.

Seguindo estas regras, vamos analisar nomes de variáveis válidos e inválidos:

Valid Invalid Why Invalid
userName user-name Hyphens are not permitted
name4 4name Cannot begin with a number
user $user Cannot use symbols
userName user name Cannot be more than one word

Além disso, lembre-se de que, ao nomear variáveis, elas diferenciam maiúsculas de minúsculas. Estes nomes userName, USERNAME, UserName e uSERnAME são todos variáveis completamente diferentes. É uma boa prática evitar o uso de nomes de variáveis semelhantes dentro de um programa para garantir que você e seus colaboradores — atuais e futuros — possam manter suas variáveis organizadas.

Embora as variáveis sejam sensíveis a maiúsculas e minúsculas, o caso da primeira letra de uma variável tem um significado especial em Go. Se uma variável começa com uma letra maiúscula, então essa variável é acessível fora do pacote em que foi declarada (ou exportada). Se uma variável começa com uma letra minúscula, então ela só está disponível dentro do pacote em que é declarada.

var Email string
var password string

Email começa com uma letra maiúscula e pode ser acessado por outros pacotes. password começa com uma letra minúscula e só é acessível dentro do pacote em que é declarado.

É comum em Go usar nomes de variáveis muito concisos (ou curtos). Dado a escolha entre usar userName e user para uma variável, seria idiomático optar por user.

O escopo também desempenha um papel na concisão do nome da variável. A regra é que quanto menor o escopo em que a variável existe, menor o nome da variável:

names := []string{"Mary", "John", "Bob", "Anna"}
for i, n := range names {
	fmt.Printf("index: %d = %q\n", i, n)
}

Utilizamos a variável names em um escopo maior, por isso é comum dar a ela um nome mais significativo para ajudar a lembrar o que ela significa no programa. No entanto, utilizamos as variáveis i e n imediatamente na próxima linha de código e, em seguida, não as utilizamos novamente… Por causa disso, não confundiremos alguém que está lendo o código sobre onde as variáveis são usadas ou o que elas significam.

Em seguida, vamos abordar algumas notas sobre o estilo das variáveis. O estilo é usar MixedCaps ou mixedCaps em vez de sublinhados para nomes de várias palavras.

Conventional Style Unconventional Style Why Unconventional
userName user_name Underscores are not conventional
i index prefer i over index as it is shorter
serveHTTP serveHttp acronyms should be capitalized

A coisa mais importante sobre o estilo é ser consistente e que a equipe com a qual você trabalha concorde com o estilo.

Reatribuição de Variáveis

Como a palavra “variável” implica, podemos alterar variáveis Go prontamente. Isso significa que podemos associar um valor diferente a uma variável previamente atribuída por meio de reatribuição. Poder reatribuir é útil porque, ao longo do curso de um programa, podemos precisar aceitar valores gerados pelo usuário em variáveis já inicializadas. Também podemos precisar alterar a atribuição para algo previamente definido.

Saber que podemos reatribuir uma variável prontamente pode ser útil ao trabalhar em um programa grande que alguém escreveu e não está claro quais variáveis já estão definidas.

Vamos atribuir o valor de 76 a uma variável chamada i do tipo int, e depois atribuir um novo valor de 42:

package main

import "fmt"

func main() {
	i := 76
	fmt.Println(i)

	i = 42
	fmt.Println(i)
}
Output
76 42

Este exemplo mostra que podemos primeiro atribuir à variável i o valor de um inteiro e, em seguida, reatribuir à variável i o valor de 42.

Nota: Quando você declara e inicializa uma variável, pode usar :=, no entanto, quando deseja simplesmente alterar o valor de uma variável já declarada, basta usar o operador de igualdade (=).

Como Go é uma linguagem tipada, não podemos atribuir um tipo a outro. Por exemplo, não podemos atribuir o valor "Sammy" a uma variável do tipo int:

i := 72
i = "Sammy"

Tentar atribuir tipos diferentes um ao outro resultará em um erro de compilação:

Output
cannot use "Sammy" (type string) as type int in assignment

Go não nos permite usar um nome de variável mais de uma vez:

var s string
var s string
Output
s redeclared in this block

Se tentarmos usar a declaração curta de variável mais de uma vez para o mesmo nome de variável, também receberemos um erro de compilação. Isso pode acontecer por engano, então entender o que a mensagem de erro significa é útil:

i := 5
i := 10
Output
no new variables on left side of :=

Da mesma forma que na declaração de variáveis, considerar a nomenclatura das suas variáveis melhorará a legibilidade do seu programa para você e para outras pessoas, quando você revisitar isso no futuro.

Atribuição Múltipla

Go também nos permite atribuir vários valores a várias variáveis na mesma linha. Cada um desses valores pode ser de um tipo de dado diferente:

j, k, l := "shark", 2.05, 15
fmt.Println(j)
fmt.Println(k)
fmt.Println(l)
Output
shark 2.05 15

Neste exemplo, a variável j foi atribuída à string "shark", a variável k foi atribuída ao float 2.05, e a variável l foi atribuída ao inteiro 15.

Essa abordagem de atribuir múltiplas variáveis a múltiplos valores em uma linha pode reduzir o número de linhas no seu código. No entanto, é importante não comprometer a legibilidade pela redução de linhas de código.

Variáveis Globais e Locais

Ao usar variáveis em um programa, é importante ter em mente o escopo da variável. O escopo de uma variável refere-se aos locais específicos onde ela é acessível dentro do código de um determinado programa. Isso significa que nem todas as variáveis são acessíveis de todas as partes de um determinado programa—algumas variáveis serão globais e outras serão locais.

Variáveis globais existem fora de funções. Variáveis locais existem dentro de funções.

Vamos ver variáveis globais e locais em ação:

package main

import "fmt"


var g = "global"

func printLocal() {
	l := "local"
	fmt.Println(l)
}

func main() {
	printLocal()
	fmt.Println(g)
}
Output
local global

Aqui, usamos `var g = "global"` para criar uma variável global fora da função. Em seguida, definimos a função `printLocal()`. Dentro da função, uma variável local chamada `l` é atribuída e depois impressa. O programa termina chamando `printLocal()` e então imprimindo a variável global `g`.

Como `g` é uma variável global, podemos referenciá-la em `printLocal()`. Vamos modificar o programa anterior para fazer isso:

package main

import "fmt"


var g = "global"

func printLocal() {
	l := "local"
	fmt.Println(l)
	fmt.Println(g)
}

func main() {
	printLocal()
	fmt.Println(g)
}
Output
local global global

Começamos declarando uma variável global `g`, `var g = "global"`. Na função `main`, chamamos a função `printLocal`, que declara uma variável local `l` e a imprime, `fmt.Println(l)`. Então, `printLocal` imprime a variável global `g`, `fmt.Println(g)`. Embora `g` não tenha sido definida dentro de `printLocal`, ainda pôde ser acessada porque foi declarada em um escopo global. Finalmente, a função `main` também imprime `g`.

Agora, vamos tentar chamar a variável local fora da função:

package main

import "fmt"

var g = "global"

func printLocal() {
	l := "local"
	fmt.Println(l)
}

func main() {
	fmt.Println(l)
}

Output
undefined: l

Não podemos usar uma variável local fora da função em que ela é atribuída. Se você tentar fazer isso, receberá um erro `undefined` ao compilar.

Vamos ver outro exemplo onde usamos o mesmo nome de variável para uma variável global e uma variável local:

package main

import "fmt"

var num1 = 5

func printNumbers() {
	num1 := 10
	num2 := 7  

	fmt.Println(num1)
	fmt.Println(num2)
}

func main() {
	printNumbers()
	fmt.Println(num1)
}
Output
10 7 5

Neste programa, declaramos a variável num1 duas vezes. Primeiro, declaramos num1 no escopo global, var num1 = 5, e novamente dentro do escopo local da função printNumbers, num1 := 10. Quando imprimimos num1 do programa main, vemos o valor de 5 impresso. Isso ocorre porque main só vê a declaração da variável global. No entanto, quando imprimimos num1 da função printNumbers, ela vê a declaração local e imprimirá o valor de 10. Embora printNumbers crie uma nova variável chamada num1 e atribua a ela um valor de 10, isso não afeta a instância global de num1 com o valor de 5.

Ao trabalhar com variáveis, também é necessário considerar quais partes do seu programa precisarão de acesso a cada variável; adotando uma variável global ou local conforme apropriado. Em programas Go, você descobrirá que variáveis locais são tipicamente mais comuns.

Constantes

Constantes são como variáveis, exceto que não podem ser modificadas uma vez declaradas. Constantes são úteis para definir um valor que será usado mais de uma vez em seu programa, mas não deve ser capaz de mudar.

Por exemplo, se quiséssemos declarar a taxa de imposto para um sistema de carrinho de compras, poderíamos usar uma constante e depois calcular o imposto em diferentes áreas do nosso programa. Em algum momento no futuro, se a taxa de imposto mudar, só precisamos alterar esse valor em um único local no nosso programa. Se usássemos uma variável, é possível que possamos alterar acidentalmente o valor em algum lugar do nosso programa, o que resultaria em um cálculo impróprio.

Para declarar uma constante, podemos usar a seguinte sintaxe:

const shark = "Sammy"
fmt.Println(shark)
Output
Sammy

Se tentarmos modificar uma constante após sua declaração, receberemos um erro em tempo de compilação:

Output
cannot assign to shark

Constantes podem ser untyped. Isso pode ser útil ao trabalhar com números como dados do tipo inteiro. Se a constante for untyped, ela é convertida explicitamente, onde constantes typed não são. Vejamos como podemos usar constantes:

package main

import "fmt"

const (
	year     = 365
	leapYear = int32(366)
)

func main() {
	hours := 24
	minutes := int32(60)
	fmt.Println(hours * year)    
	fmt.Println(minutes * year)   
	fmt.Println(minutes * leapYear)
}
Output
8760 21900 21960

Se você declarar uma constante com um tipo, ela será exatamente desse tipo. Aqui, ao declarar a constante leapYear, definimos como tipo de dado int32. Portanto, é uma constante typed, o que significa que só pode operar com tipos de dados int32. A constante year que declaramos sem tipo, então é considerada untyped. Por causa disso, você pode usá-la com qualquer tipo de dado inteiro.

Quando hours foi definido, ele inferiu que era do tipo int porque não demos a ele um tipo explicitamente, hours := 24. Quando declaramos minutes, declaramos explicitamente como int32, minutes := int32(60).

Agora, vamos analisar cada cálculo e por que ele funciona:

hours * year

Neste caso, hours é um int, e years é não tipado. Quando o programa compila, ele converte explicitamente years para um int, o que permite que a operação de multiplicação tenha sucesso.

minutes * year

Neste caso, minutes é um int32, e year é não tipado. Quando o programa compila, ele converte explicitamente years para um int32, o que permite que a operação de multiplicação tenha sucesso.

minutes * leapYear

Neste caso, minutes é um int32, e leapYear é uma constante tipada de int32. Não há nada para o compilador fazer desta vez, pois ambas as variáveis já são do mesmo tipo.

Se tentarmos multiplicar dois tipos que são tipados e não compatíveis, o programa não compilará:

fmt.Println(hours * leapYear)
Output
invalid operation: hours * leapYear (mismatched types int and int32)

Neste caso, hours foi inferido como um int, e leapYear foi explicitamente declarado como um int32. Como Go é uma linguagem tipada, um int e um int32 não são compatíveis para operações matemáticas. Para multiplicá-los, você precisaria converter um para um int32 ou um int.

Conclusão

Neste tutorial, revisamos alguns dos casos de uso comuns de variáveis no Go. Variáveis são um bloco de construção importante da programação, servindo como símbolos que representam o valor de um tipo de dado que utilizamos em um programa.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-variables-and-constants-in-go