Menu

Arrays em Golang: tamanho fixo, semântica de valor e diferença para slices

Um array em Go tem tamanho fixo, que faz parte do seu tipo, e é copiado na atribuição. Veja como declarar, percorrer, comparar e passar arrays, e por que a maior parte do código Go usa slices no lugar.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

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]TSlice []T
Tamanhofixo, faz parte do tipomuda com append
Atribuição e passagemcopia todos os elementoscopia um cabeçalho pequeno, compartilha os elementos
Valor zeroN elementos zeronil, tamanho 0
==sim, elemento por elementosó com nil
Chave de mapsimnão
Uso típicodados de tamanho fixo: hashes, coordenadas, buffersquase 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]T ou 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 []int não aceita um [2]int; passe a[:].
  • Arrays grandes em um laço com range. for _, v := range bigArray copia o array inteiro antes. Faça range sobre &bigArray ou 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.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR