Declarando um array
Um tipo array se escreve [N]T: um tamanho e depois o tipo do elemento. O tamanho é fixado em tempo de compilação e faz parte do tipo.
Saída:
[90 0 0 0 75] 5
Tue
[5]int [2 3 5 7 11]
["" "b" "" "d" ""]
Um array está sempre totalmente inicializado. Elementos que você não define guardam o valor zero do tipo do elemento: 0, "", false, nil.
Indexação e limites
Os índices vão de 0 a len(a)-1. Um índice constante fora da faixa é erro de compilação. Um índice variável fora da faixa causa panic em tempo de execução.
var a [3]int
a[5] = 1 // compile error: invalid argument: index 5 out of bounds [0:3]
i := 5
a[i] = 1 // panic: runtime error: index out of range [5] with length 3
Percorrendo
for i, v := range a visita cada elemento em ordem. v é uma cópia do elemento, então atribuir a v não muda o array. Escreva pelo índice.
Existe mais uma sutileza específica de arrays: o range sobre um valor de array avalia uma cópia do array logo no início. Se o corpo alterar elementos mais adiante, v ainda mostra os valores antigos. Fazer range sobre &a ou a[:] evita a cópia.
Arrays são valores
Essa é a principal diferença em relação aos arrays de C, Java ou JavaScript. Atribuir um array copia todos os elementos. Passar um array para uma função também o copia.
Saída:
[1 2 3] [99 2 3]
[1 2 3]
[0 2 3]
Copiar é barato para arrays pequenos e caro para os grandes: passar um [1_000_000]int por valor copia oito megabytes. Passe um ponteiro (*[N]T) ou um slice (a[:]) quando o array for grande ou a função precisar alterá-lo. Indexar por um ponteiro de array não exige * explícito: a[0] funciona em um *[3]int.
Comparando arrays e usando-os como chave de map
Arrays de elementos comparáveis aceitam == e !=. Dois arrays são iguais quando todos os elementos são iguais. Isso também os torna chaves de map válidas, o que slices não são.
Arrays de tamanhos diferentes são tipos diferentes e não podem ser comparados de jeito nenhum: [3]int{} == [4]int{} não compila (mismatched types [3]int and [4]int).
Arrays multidimensionais
Um array de arrays dá uma grade fixa. A grade inteira é um único bloco contíguo de memória.
row[:] transforma a linha [3]rune em um slice []rune, que string() aceita.
Arrays ou slices
Array [N]T | Slice []T | |
|---|---|---|
| Tamanho | fixo, faz parte do tipo | muda com append |
| Atribuição e passagem | copia todos os elementos | copia um cabeçalho pequeno, compartilha os elementos |
| Valor zero | N elementos zero | nil, tamanho 0 |
== | sim, elemento por elemento | só com nil |
| Chave de map | sim | não |
| Uso típico | dados de tamanho fixo: hashes, coordenadas, buffers | quase todo o resto |
Na prática, você vai encontrar arrays principalmente em poucos lugares: sha256.Sum256 devolve um [32]byte, tabelas de consulta cujo tamanho nunca muda e como armazenamento por trás de um slice. Fatiar um array com a[:] ou a[1:3] cria um slice que compartilha a memória dele; a página de slices explica o que esse compartilhamento significa.
Convertendo entre arrays e slices
Converter um slice em array (Go 1.20) ou em ponteiro de array (Go 1.17) causa panic se o slice for menor que o tamanho do array: panic: runtime error: cannot convert slice with length 2 to array or pointer to array with length 3.
Erros comuns
- Esperar que uma função altere um array passado como argumento. Ela recebe uma cópia. Passe
*[N]Tou um slice. - Usar um array onde se espera um slice.
[]int{1, 2}é um slice,[2]int{1, 2}é um array. Uma função que recebe[]intnão aceita um[2]int; passea[:]. - Arrays grandes em um laço com range.
for _, v := range bigArraycopia o array inteiro antes. Faça range sobre&bigArrayou sobre um slice.
Perguntas frequentes
Como declarar um array em Go?
Escreva o tamanho entre colchetes antes do tipo do elemento: var a [5]int cria cinco zeros. Com valores: a := [3]string{"x", "y", "z"}. Use [...] para o compilador contar: a := [...]int{1, 2, 3} tem tipo [3]int.
Qual a diferença entre array e slice em Go?
Um array tem tamanho fixo, que faz parte do tipo ([3]int e [4]int são tipos diferentes), e é copiado ao ser atribuído ou passado. Um slice ([]int) é uma visão sobre um array subjacente, com um tamanho que pode mudar por meio do append, e copiar um slice copia só a visão, não os elementos. A maior parte do código Go usa slices.
Como obter o tamanho de um array em Go?
Use a função embutida len(a). Para um array, ela é uma constante de tempo de compilação, então pode ser usada em expressões constantes. cap(a) devolve o mesmo número.
Dá para comparar arrays em Go?
Sim, com == e !=, se o tipo do elemento for comparável. Dois arrays são iguais quando todos os seus elementos são iguais. Arrays também podem ser chaves de map. Slices não podem ser comparados com == (exceto com nil); use slices.Equal para eles.