Exercício - Usar matrizes
Matrizes em Go são uma estrutura de dados de comprimento fixo de um tipo específico. Eles podem ter zero ou mais elementos, e você precisa definir o tamanho ao declará-los ou inicializá-los. Além disso, não é possível redimensioná-los depois de criados. Por esses motivos, matrizes não são comumente usadas em programas Go, mas são a base para fatias e mapas.
Declarar matrizes
Para declarar uma matriz em Go, você precisa definir o tipo de dados de seus elementos e o número de elementos que a matriz pode conter. Em seguida, você pode acessar cada elemento na matriz com a notação subscrita, onde zero é o primeiro elemento e o último elemento é um a menos que o comprimento da matriz (comprimento - 1).
Por exemplo, vamos usar o seguinte código:
package main
import "fmt"
func main() {
var a [3]int
a[1] = 10
fmt.Println(a[0])
fmt.Println(a[1])
fmt.Println(a[len(a)-1])
}
Quando você executa o código anterior, você obtém a seguinte saída:
0
10
0
Mesmo que você tenha declarado uma matriz, não receberá um erro ao acessar seus elementos. Por padrão, Go inicializa cada elemento com o tipo de dados padrão. Nesse caso, o valor padrão para int
é zero. Mas você pode atribuir um valor a uma posição específica, como fizemos com a[1] = 10
o . E você pode acessar esse elemento usando a mesma notação. Além disso, observe que para fazer referência ao primeiro elemento, usamos a[0]
. Para fazer referência ao último elemento, usamos a[len(a)-1]
. A len
função é uma função interna em Go para obter o número de elementos em uma matriz, fatia ou mapa.
Inicializar matrizes
Você também pode inicializar uma matriz com outros valores além dos padrões quando estiver declarando uma matriz. Por exemplo, você pode usar o código a seguir para ver e testar a sintaxe:
package main
import "fmt"
func main() {
cities := [5]string{"New York", "Paris", "Berlin", "Madrid"}
fmt.Println("Cities:", cities)
}
Execute o código anterior e você verá esta saída:
Cities: [New York Paris Berlin Madrid ]
Embora a matriz deva ter cinco elementos, não precisamos atribuir um valor a todos os elementos. Como vimos antes, a última posição tem uma cadeia de caracteres vazia porque é o valor padrão para um tipo de dados de cadeia de caracteres.
Elipse em matrizes
Outra maneira de declarar e inicializar uma matriz quando você não sabe quantas posições precisará, mas conhece o conjunto de elementos de dados, é usar reticências (...
), como este exemplo:
q := [...]int{1, 2, 3}
Vamos modificar o programa que usamos na seção anterior para usar reticências. O código deve ser semelhante a este exemplo:
package main
import "fmt"
func main() {
cities := [...]string{"New York", "Paris", "Berlin", "Madrid"}
fmt.Println("Cities:", cities)
}
Execute o código anterior e você verá uma saída semelhante, como este exemplo:
Cities: [New York Paris Berlin Madrid]
Consegue ver a diferença? Não há nenhuma string vazia no final. O comprimento da matriz foi determinado pelas cadeias de caracteres que você colocou quando a inicializou. Você não está reservando memória que você não sabe se vai acabar precisando.
Outra maneira interessante de inicializar uma matriz é usar reticências e especificar apenas um valor para a última posição. Por exemplo, use o seguinte código:
package main
import "fmt"
func main() {
numbers := [...]int{99: -1}
fmt.Println("First Position:", numbers[0])
fmt.Println("Last Position:", numbers[99])
fmt.Println("Length:", len(numbers))
}
Execute este código e você obterá esta saída:
First Position: 0
Last Position: -1
Length: 100
Observe como o comprimento da matriz é 100 porque você especificou um valor para a posição 99. A primeira posição imprime o valor padrão (zero).
Matrizes multidimensionais
O Go tem suporte para matrizes multidimensionais quando você precisa trabalhar com estruturas de dados complexas. Vamos criar um programa onde você declara e inicializa uma matriz bidimensional. Utilize o seguinte código:
package main
import "fmt"
func main() {
var twoD [3][5]int
for i := 0; i < 3; i++ {
for j := 0; j < 5; j++ {
twoD[i][j] = (i + 1) * (j + 1)
}
fmt.Println("Row", i, twoD[i])
}
fmt.Println("\nAll at once:", twoD)
}
Execute o programa anterior e você verá uma saída como este exemplo:
Row 0 [1 2 3 4 5]
Row 1 [2 4 6 8 10]
Row 2 [3 6 9 12 15]
All at once: [[1 2 3 4 5] [2 4 6 8 10] [3 6 9 12 15]]
Você declarou uma matriz bidimensional que especifica quantas posições a matriz teria na segunda dimensão, como esta var twoD [3][5]int
. Você pode pensar nessa matriz como uma estrutura de dados com colunas e linhas, como uma planilha ou uma matriz. Neste ponto, todas as posições têm um valor padrão de zero. for
No loop, estamos inicializando cada posição com um padrão de valor diferente em cada linha. Finalmente, você imprime todos os seus valores no terminal.
E se você quiser declarar uma matriz tridimensional? Bem, você pode adivinhar qual seria a sintaxe, certo? Você pode fazê-lo como este exemplo:
package main
import "fmt"
func main() {
var threeD [3][5][2]int
for i := 0; i < 3; i++ {
for j := 0; j < 5; j++ {
for k := 0; k < 2; k++ {
threeD[i][j][k] = (i + 1) * (j + 1) * (k + 1)
}
}
}
fmt.Println("\nAll at once:", threeD)
}
Execute o código anterior e você verá uma saída como este exemplo:
All at once: [[[1 2] [2 4] [3 6] [4 8] [5 10]] [[2 4] [4 8] [6 12] [8 16] [10 20]] [[3 6] [6 12] [9 18] [12 24] [15 30]]]
Se formatarmos a saída em um formato mais legível, você pode ter algo como este exemplo:
All at once:
[
[
[1 2] [2 4] [3 6] [4 8] [5 10]
]
[
[2 4] [4 8] [6 12] [8 16] [10 20]
]
[
[3 6] [6 12] [9 18] [12 24] [15 30]
]
]
Observe como a estrutura muda a partir de uma matriz bidimensional. Você pode continuar tendo mais dimensões conforme necessário, mas vamos deixar isso aqui por enquanto porque temos outros tipos de dados para explorar.