Introdução a Variáveis em Go

GolangBeginner
Pratique Agora

Introdução

Por que precisamos de variáveis em linguagens de programação de computadores? Esta é uma questão antiga. Assim como podemos lembrar que o URL do LabEx é labex.io, os programas de computador também precisam lembrar alguns dados para seu uso.

O propósito das variáveis é representar um pedaço de dados. Nesta seção, exploraremos como as variáveis são usadas na linguagem Go.

Pontos de Conhecimento:

  • Declaração de variáveis
  • Inicialização de variáveis
  • Uso de variáveis
  • Tempo de vida da variável (Variable lifetime)
  • Constantes

O que é uma Variável?

O que é uma variável? Em termos simples, uma variável é um contêiner usado para armazenar e salvar um pedaço de dados mutáveis (mutable).

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

O que Significa um Tipo de Variável Ser Fixo?

Significa que uma variável só pode conter um tipo de dado. Em outras palavras, os itens armazenados no contêiner da variável são fixos.

Se uma variável é usada para conter frutas, ela só deve conter frutas. Uma vez que o contêiner tenha contido frutas, ele não pode ser usado para conter biscoitos. Isso se reflete no código, pois uma variável não pode ser atribuída com dois tipos diferentes de dados.

Mutabilidade da Variável

Como o nome sugere, o valor de uma variável pode mudar, desde que a mudança não exceda a faixa permitida por seu tipo.

A linguagem Go tem as seguintes regras para variáveis:

  • O nome deve consistir em 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. Verifique as palavras-chave reservadas
  • Os nomes das variáveis são sensíveis a maiúsculas e minúsculas, mas não é recomendado usar capitalização diferente para distinguir entre duas variáveis com o mesmo nome.

Método Geral de Declaração

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

A forma de declaração é: var identificador tipo, o que significa:

var nomeDaVariavel tipoDaVariavel.

Quais são os tipos de variáveis 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 envolvida em 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, apenas os três tipos mais comuns são listados.

Mais tipos serão explicados nos cursos seguintes.

Como declaramos uma variável?

Agora, vamos declarar uma variável inteira chamada a.

var a int

Como lembrar? Você pode dizer silenciosamente em sua mente:

Defina uma variável chamada `a`, que é do tipo int.

Ao contrário de muitas linguagens de programação tradicionais, o tipo de variável usado em Go é colocado após o nome da variável.

Essa forma de declarar variáveis torna o código mais fácil de ler da esquerda para a direita e evita a lógica de leitura em espiral da linguagem C. Para 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, precisamos prestar atenção à sua expressividade e evitar o uso de abreviações.

Aqui, apresentaremos brevemente o método básico de nomeação de variáveis: Convenção de Nomenclatura Camel Case.

A convenção de nomenclatura Camel Case usa letras em caixa mista para representar uma variável. A primeira palavra está em minúsculas e a primeira letra de cada palavra subsequente é capitalizada.

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

Dessa forma, uma variável que representa a data atual é facilmente compreendida.

Essa convenção de nomenclatura é geralmente usada para variáveis importantes e comumente usadas, enquanto variáveis temporárias podem ser simplificadas, desde que não causem duplicação.

Método de Declaração em Lote

Agora, vamos declarar 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

Os alunos observadores podem ter notado 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

Parece que encontramos uma situação semelhante ao importar pacotes. Muitos pacotes com nomes diferentes precisam ser importados juntos, então podemos usar um método de escrita semelhante:

var (
    a int
    b string
    c bool
)

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

Inicialização Padrão

Em Go, todas as variáveis recebem valores iniciais quando são declaradas. Vamos explorar quais são os valores iniciais das variáveis!

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

touch ~/project/varExercise.go

Escreva o seguinte código 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)
}

Você pode tentar executá-lo e ver se corresponde à tabela abaixo.

go run varExercise.go

Os tipos de valores iniciais são resumidos da seguinte forma:

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

Inicialização Padrão

Como o tipo de uma variável pode ser determinado por seu valor inicial, podemos alterar o valor padrão ou 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, só precisamos adicionar = após declarar a variável, seguido por um valor inicial que seja compatível com o tipo da variável. Se você quiser alterar o valor, basta usar o nome da variável seguido por = 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)
}

Após executar o código, a saída é a seguinte:

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

Você pode tentar executá-lo e modificar os valores iniciais.

Acabamos de mencionar que o valor inicial atribuído a uma variável deve ser do mesmo tipo da declaração da variável. O que acontecerá se forem diferentes?

Por exemplo, vamos atribuir "labex" como o 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 na figura, não podemos atribuir um tipo string como "labex" a uma variável do tipo int. Isso ocorre porque Go é uma linguagem compilada de tipagem forte e não pode ser compilada.

Declaração de Tipo por Inferência

Como Go pode determinar o tipo de uma variável por seu valor inicial, podemos simplificar o processo de declaração de tipo eliminando a etapa de especificar explicitamente o 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
// Declare variables a, b, c as integers and assign an initial value of 0
a, b, c := 0, "", true
// Declare variables a, b, c as integer, string, and boolean, respectively

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

Às vezes, escrevemos o seguinte código:

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 redeclarada. No entanto, se for escrito da seguinte forma:

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

Há essa saída porque o a com valor 1 acima e o a com valor 2 abaixo não estão no mesmo escopo de variável (dentro das mesmas chaves), então o compilador os trata como duas variáveis diferentes.

O compilador não apontará seu erro, mas haverá uma saída inesperada.

Em Go, está estipulado que:

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

Portanto, a declaração abreviada de variável só pode ser usada para declarar variáveis locais e não pode ser usada para declarar variáveis globais.

Então, o que é uma variável global e o que é uma variável local?

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

Escopo de Variável

O escopo de variável se refere ao intervalo em que uma variável em um programa é efetiva, ou seja, como ela pode ser usada.

Você deve ter notado que, se você declarar uma variável, mas não usá-la, o código não será compilado.

Em outras palavras, quando o Go é compilado, ele verifica se cada variável foi usada, ou seja, se foi usada dentro de seu escopo.

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

  • Variáveis definidas dentro de uma função, chamadas de variáveis locais
  • Variáveis definidas fora de uma função, chamadas de variáveis globais
  • Variáveis definidas dentro de uma definição de função, chamadas de 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)
}

Variáveis locais são definidas dentro do corpo da função, como a definido dentro da função main. O escopo da variável a é limitado a dentro da função main.

Ao mesmo tempo, se a variável não for usada na função main, o compilador lançará um erro.

Variáveis Globais

No entanto, 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)
}

Variáveis globais são definidas fora do corpo da função, e seu escopo abrange todo o programa. Mesmo que não sejam chamadas em nenhuma função, um erro não será relatado pelo compilador.

Você pode pensar por que as variáveis globais não produzirão erros, mesmo que não sejam chamadas.

Resposta

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

Detalhes sobre variáveis de parâmetro formal serão explicados em cursos subsequentes relacionados a funções.

Tempo de Vida da Variável

Pássaros que voam para longe, escondem o alcance. Coelhos ardilosos morrem, e cães serão cozidos. - Registros do Grande Historiador

Quando uma variável concluiu seu propósito, ela deve ser destruída para reduzir o uso de memória.

  • Variáveis globais: O tempo de vida de uma variável global é consistente com todo o tempo de execução do programa. Quando o programa para de ser executado, a variável global é limpa da memória.
  • Variáveis locais: Quando não há como acessar uma variável, seu espaço de memória será recuperado.

Tal design é a chave para o alto desempenho e o uso eficiente do espaço do Go.

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

Você pode escrever o seguinte 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)
}

Após 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 nos diz que a foi definido novamente.

Constantes

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

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

Constantes são muito semelhantes a variáveis, e você pode até pensar nelas como variáveis com valores imutáveis.

Ao declarar uma constante, só precisamos substituir a palavra-chave var pela palavra-chave const.

const Pi = 3.14159 // Usando inicialização por inferência de tipo

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 nos diz que o valor de Pi não pode ser reassignado.

Ao declarar uma constante, devemos fornecer um valor inicial.

E o valor inicial atribuído a uma constante deve ser fixo no tempo de compilação.

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

var a int = 1
// Valor é fixo, declaração é válida.
const Pi = 3.14159
// O valor calculado também é fixo, a declaração é válida.
const c = 1 / Pi
// Valor de retorno fixo da função embutida é válido.
const le = len("labex")
// O valor de retorno da função definida pelo usuário não é fixo, a declaração é inválida.
const le = getLen("labby")
// `a` é um valor de variável que não é fixo, a declaração é inválida.
const k = a

Se uma declaração de constante é válida pode ser resumida na seguinte tabela:

Tipo de Declaração Válido
Valores fixos e expressões de valor fixo Válido
Valores não fixos (variáveis) e suas expressões correspondentes Inválido
Função embutida (len()) recebe um valor fixo e expressões de valor fixo Válido
Funções definidas pelo usuário Inválido

Resumo

Vamos rever o que aprendemos neste laboratório:

  • As formas de declarar variáveis
  • As formas de inicializar variáveis
  • O conceito de tempo de vida da variável
  • O uso de constantes e se suas declarações são válidas

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