Introdução às variáveis em Go

GolangBeginner
Pratique Agora

Introdução

Por que precisamos de variáveis nas linguagens de programação? Essa é uma pergunta antiga. Assim como podemos lembrar que a URL do LabEx é labex.io, os programas de computador também precisam guardar alguns dados para utilizá-los.

As variáveis têm a finalidade de representar uma parte dos dados. Nesta seção, você aprenderá como as variáveis são usadas na linguagem Go.

Conhecimentos abordados:

  • Declaração de variáveis
  • Inicialização de variáveis
  • Uso de variáveis
  • Tempo de vida das variáveis
  • Constantes

O que é uma variável?

Nesta etapa, você aprenderá o que as variáveis representam e como Go restringe seus nomes e tipos.

O que é uma variável? Em termos simples, uma variável é um contêiner usado para armazenar e guardar uma parte de dados mutáveis.

Em linguagens compiladas, como Go, o tipo de uma variável é fixo.

O que significa o tipo de uma variável ser fixo?

Isso significa que uma variável pode armazenar apenas um tipo de dado. Em outras palavras, os itens armazenados no contêiner da variável são fixos.

Se uma variável for usada para armazenar frutas, ela deverá armazenar apenas frutas. Depois que o contêiner tiver armazenado frutas, ele não poderá ser usado para armazenar biscoitos. No código, isso significa que uma variável não pode receber dados de dois tipos diferentes.

Mutabilidade das variáveis

Como o próprio nome indica, o valor de uma variável pode mudar, desde que essa mudança não ultrapasse o intervalo permitido pelo tipo da variável.

A linguagem Go segue estas regras para as variáveis:

  • O nome deve ser formado por letras, dígitos e sublinhados.
  • O identificador da variável não pode começar com um dígito.
  • O identificador não pode ser uma palavra-chave reservada. Confira as palavras-chave reservadas
  • Os nomes de variáveis diferenciam maiúsculas de minúsculas, mas não é recomendado usar capitalizações diferentes para distinguir duas variáveis com o mesmo nome.

Método geral de declaração

Nesta etapa, você aprenderá a declarar uma variável tipada usando a palavra-chave var.

Na linguagem Go, a palavra-chave usada para declarar variáveis pelo método geral é var.

A forma da declaração é var identifier type, que significa:

var variableName variableType.

Quais são os tipos de variáveis mais comuns em Go?

Palavra-chave Explicação
int Inteiro. O tipo de dado mais comum, ensinado na matemática do ensino fundamental.
string String. Uma sequência de caracteres entre aspas duplas, como: "hello,world"
bool Booleano. Representa verdadeiro ou falso, com dois valores possíveis: true ou false

Como os tipos de variáveis não são o foco desta seção, listamos apenas os três tipos mais comuns.

Outros tipos serão explicados nos próximos cursos.

Como declaramos uma variável?

Agora, declare uma variável inteira chamada a.

var a int

Como memorizar essa declaração? Você pode dizer mentalmente:

Define a variable named `a`, which is of type int.

Ao contrário de muitas linguagens de programação tradicionais, em Go o tipo da variável vem depois do nome da variável.

Essa forma de declarar variáveis facilita a leitura do código da esquerda para a direita e evita a lógica de leitura em espiral da linguagem C. Para obter mais detalhes, consulte a documentação oficial.

Que nome devemos dar a uma variável?

Um bom nome de variável deve indicar claramente o significado da variável.

Ao nomear variáveis, você deve prestar atenção à clareza do nome e evitar abreviações.

Aqui, apresentaremos brevemente o método básico de nomenclatura de variáveis: a convenção de nomenclatura Camel Case.

A convenção Camel Case usa letras com maiúsculas e minúsculas combinadas para representar uma variável. A primeira palavra começa com letra minúscula, e a primeira letra de cada palavra seguinte é maiúscula.

Por exemplo: currentDate. A primeira palavra, current, começa com letra minúscula, e a segunda palavra, Date, começa com letra maiúscula.

Dessa forma, é fácil entender que a variável representa a data atual.

Essa convenção geralmente é usada para variáveis importantes e usadas com frequência. Variáveis temporárias podem ter nomes mais simples, desde que isso não cause duplicidade.

Método de declaração em lote

Nesta etapa, você aprenderá a declarar várias variáveis de uma só vez.

Agora, declare três variáveis:

var a int // Declare an integer variable named a
var b int // Declare an integer variable named b
var c int // Declare an integer variable named c

Você pode ter percebido que as três variáveis, a, b, c, são do tipo int.

Nesse caso, podemos usar uma vírgula para conectar os nomes das variáveis e reduzir a quantidade de código.

var a, b, c int // Declare three variables a, b, c as integers

Mas e se as três variáveis tiverem tipos diferentes?

var a int    // Declare an integer variable named a
var b string // Declare a string variable named b
var c bool   // Declare a boolean variable named c

Essa situação é semelhante ao que ocorre ao importar pacotes. Como vários pacotes com nomes diferentes precisam ser importados juntos, podemos usar uma forma de escrita semelhante:

var (
    a int
    b string
    c bool
)

Observe que esse tipo de declaração, semelhante à importação de pacotes, geralmente é usado para definir variáveis globais.

Inicialização padrão

Nesta etapa, você verificará os valores padrão que Go atribui às variáveis.

Em Go, todas as variáveis recebem valores iniciais quando são declaradas. Vamos descobrir quais são esses valores iniciais.

Crie um arquivo chamado varExercise.go no diretório ~/project.

touch ~/project/varExercise.go

Escreva o código a seguir no arquivo:

package main

import "fmt"

func main() {
    var a int
    var b string
    var c bool
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}

Execute o programa e verifique se o resultado corresponde à tabela abaixo.

go run varExercise.go

Os valores iniciais são resumidos a seguir:

Palavra-chave Explicação Valor inicial
int Inteiro 0
string String ""
bool Booleano false

Inicialização explícita

Nesta etapa, você inicializará variáveis explicitamente e depois atribuirá novos valores a elas.

Como o tipo de uma variável pode ser determinado pelo seu valor inicial, podemos alterar o valor padrão de uma variável já declarada?

var a int = 1
var b string = "labex"
var c bool = true

a = 233
b = "labex"
c = false

Como mostrado acima, basta adicionar = depois de declarar a variável e, em seguida, informar um valor inicial compatível com o tipo da variável. Para alterar o valor, use o nome da variável seguido de = e outro valor do mesmo tipo.

Modifique o arquivo varExercise.go:

package main

import "fmt"

func main() {
    // Declare and initialize
    var a int = 1
    var b string = "labex"
    var c bool = true

    // Print the variables
    fmt.Println("Before modification:")
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)

    // Modify the variables
    a = 233
    b = "labex"
    c = false

    // Print the modified variables
    fmt.Println("After modification:")
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}

Depois de executar o código, a saída será:

$ go run varExercise.go
Before modification:
1
labex
true
After modification:
233
labex
false

Execute o programa e experimente modificar os valores iniciais.

Mencionamos que o valor inicial atribuído a uma variável deve ter o mesmo tipo declarado para ela. O que acontece quando os tipos são diferentes?

Por exemplo, vamos atribuir "labex" como valor inicial à variável a:

package main

import "fmt"

func main() {
    var a int = "labex"
    fmt.Println(a)
}

Execute o código:

$ go run varExercise.go
## command-line-arguments
./varExercise.go:6:12: cannot use "labex" (type untyped string) as type int in assignment

Como mostrado no exemplo, não podemos atribuir uma string, como "labex", a uma variável do tipo int. Isso acontece porque Go é uma linguagem compilada e fortemente tipada, portanto o código não pode ser compilado.

Declaração de tipo por inferência

Nesta etapa, você declarará variáveis locais usando inferência de tipos e o operador :=.

Como Go consegue determinar o tipo de uma variável a partir do seu valor inicial, podemos simplificar a declaração eliminando a especificação explícita do tipo?

package main

import "fmt"

func main() {
    // var a int = 1
    var a = 1 // Type is inferred
    fmt.Println(a)
}

Agora, você nem precisa usar a palavra-chave var para definir uma variável.

Essa forma de declarar e inicializar uma variável também pode ser combinada com o método de declaração em lote:

a, b, c := 0, 0, 0
// Declare variables a, b, c as integers and assign 0 to each variable.

Como alternativa, inicialize as variáveis com valores de tipos diferentes:

a, b, c := 0, "", true
// Declare variables a, b, c as integer, string, and boolean, respectively.

Cada variável à esquerda de := precisa ter um valor inicial correspondente à direita.

A declaração curta é muito conveniente, mas tenha cuidado: := não é uma operação de atribuição. Ela é uma forma de declarar variáveis exclusiva de Go, usada para declarar e inicializar variáveis locais dentro de uma função. O tipo da variável será inferido automaticamente com base na expressão.

Às vezes, escrevemos o código a seguir:

func main() {
    a := 1
    println(a)
    a := 2
    println(a)
}

O compilador informará que há um erro no código porque a variável a foi declarada novamente. No entanto, se o código for escrito assim:

func main() {
    a := 1
    if true {
        a := 2
        println(a) // Output: 2
    }
    println(a) // Output: 1
}

Essa saída ocorre porque a variável a com valor 1 e a variável a com valor 2 não estão no mesmo escopo de variável, ou seja, dentro das mesmas chaves. Por isso, o compilador trata as duas como variáveis diferentes.

O compilador não apontará esse erro, mas a saída será inesperada.

Em Go, existe a seguinte regra:

Cada instrução fora de uma função deve começar com uma palavra-chave (var, func etc.).

Portanto, a declaração curta de variáveis só pode ser usada para declarar variáveis locais; ela não pode ser usada para declarar variáveis globais.

Então, o que são variáveis globais e variáveis locais?

Isso envolve o conceito de tempo de vida das variáveis, que será explicado na próxima seção.

Escopo das variáveis

Nesta etapa, você comparará os escopos das variáveis locais, das variáveis globais e dos parâmetros formais.

O escopo de uma variável é o intervalo em que ela é válida em um programa, ou seja, onde ela pode ser usada.

Você provavelmente percebeu que, se declarar uma variável e não a utilizar, o código não será compilado.

Em outras palavras, durante a compilação de Go, o compilador verifica se cada variável foi usada, isto é, se ela foi usada dentro do próprio escopo.

Podemos dividir as variáveis em três tipos, de acordo com a posição de suas declarações:

  • Variáveis definidas dentro de uma função, chamadas variáveis locais
  • Variáveis definidas fora de uma função, chamadas variáveis globais
  • Variáveis definidas na declaração de uma função, chamadas parâmetros formais

Variáveis locais

Nesta seção, a maioria das variáveis que definimos são variáveis locais:

package main

import "fmt"

func main() { // Function body
    var a int = 1 // Local variable
    fmt.Println(a)
}

As variáveis locais são definidas dentro do corpo de uma função, como a, definida dentro da função main. O escopo da variável a está limitado à função main.

Além disso, se a variável não for usada na função main, o compilador emitirá um erro.

Variáveis globais

Também é possível definir uma variável global.

package main

import "fmt"

var a int = 1 // Global variable
func main() { // Function body
    fmt.Println(a)
}

As variáveis globais são definidas fora do corpo de uma função, e seu escopo abrange todo o programa. Mesmo que não sejam chamadas em nenhuma função, o compilador não emitirá um erro.

Reflita sobre por que as variáveis globais não geram erros mesmo quando não são chamadas.

Resposta

Isso acontece porque a variável global pode ser chamada em outro pacote.

Os detalhes sobre variáveis de parâmetros formais serão explicados em cursos posteriores relacionados a funções.

Tempo de vida das variáveis

Nesta etapa, você aprenderá por quanto tempo as variáveis permanecem acessíveis e por que uma variável não pode ser declarada novamente no mesmo escopo.

Pássaros que voam para longe escondem a extensão. Coelhos astutos morrem, e os cães de caça cozinham. — Registros do Grande Historiador

Quando uma variável conclui sua finalidade, ela deve ser destruída para reduzir o uso de memória.

  • Variáveis globais: o tempo de vida de uma variável global corresponde a toda a execução do programa. Quando o programa para de executar, a variável global é removida da memória.
  • Variáveis locais: quando não há mais nenhuma forma de acessar uma variável, o espaço de memória ocupado por ela é recuperado.

Esse design é fundamental para o alto desempenho e o uso eficiente de espaço em Go.

Durante o tempo de vida de uma variável, ela não pode ser declarada novamente.

Você pode escrever o código a seguir em varExercise.go:

package main

import "fmt"

func main() {
    var a int = 1 // Local variable, lifetime is limited to the entire main function
    var a int = 2 // Redefinition
    fmt.Println(a)
}

Depois de executar o código:

go run varExercise.go

Você verá a seguinte mensagem de erro:

./varExercise.go:7:9: a redeclared in this block
previous declaration at ./varExercise.go:6:9

O compilador informa que a foi definida novamente.

Constantes

Nesta etapa, você declarará constantes e identificará quais expressões são valores constantes válidos.

Muitas coisas na vida são como constantes. Podemos percebê-las, mas não podemos alterá-las.

Se o valor de uma variável não mudar durante toda a execução do programa, devemos defini-la como uma constante.

As constantes são muito semelhantes às variáveis. Você pode até pensar nelas como variáveis com valores imutáveis.

Ao declarar uma constante, basta substituir a palavra-chave var pela palavra-chave const.

const Pi = 3.14159 // Using type inference initialization

Crie um arquivo chamado constExercise.go no diretório ~/project.

touch ~/project/constExercise.go

O que acontecerá se tentarmos modificar uma constante?

package main

import "fmt"

func main() {
    const Pi = 3.14159
    Pi = 2 // Error: cannot assign to Pi
    fmt.Println(Pi)
}

Execute o código.

$ go run constExercise.go
## command-line-arguments
./constExercise.go:7:8: cannot assign to Pi

O compilador informa que não é possível atribuir um novo valor a Pi.

Ao declarar uma constante, você deve fornecer um valor inicial.

Além disso, o valor inicial atribuído a uma constante deve ser fixo no momento da compilação.

Os valores retornados por funções definidas pelo usuário não são considerados fixos em Go.

var a int = 1
// Value is fixed, declaration is valid.
const Pi = 3.14159
// The calculated value is also fixed, the declaration is valid.
const c = 1 / Pi
// Fixed return value from built-in function is valid.
const le = len("labex")
// The return value of the user-defined function is not fixed, the declaration is invalid.
const le = getLen("labby")
// `a` is a variable value that is not fixed, the declaration is invalid.
const k = a

A validade de uma declaração de constante pode ser resumida na tabela a seguir:

Tipo de declaração Válida
Valores fixos e expressões com valores fixos Válida
Valores não fixos (variáveis) e suas expressões correspondentes Inválida
A função integrada (len()) recebe um valor fixo e expressões com valores fixos Válida
Funções definidas pelo usuário Inválida

Resumo

Vamos revisar o que você aprendeu neste laboratório:

  • As formas de declarar variáveis
  • As formas de inicializar variáveis
  • O conceito de tempo de vida das variáveis
  • O uso de constantes e a validade de suas declarações

Neste laboratório, revisamos o uso básico de variáveis em Go, demonstramos formas de declarar e usar variáveis em diferentes situações e apresentamos as constantes.