Sobes.tech
Junior

Como funcionam os slices em Go?

sobes.tech IA

Resposta da IA

Um slice é uma camada leve sobre um array. Ele não armazena dados por si só, mas referencia um array base.

Estrutura do slice:

  • Ponteiro para o array base: Endereço do primeiro elemento do slice na memória.
  • Comprimento (Length): Número de elementos no slice.
  • Capacidade (Capacity): Número de elementos no array base, disponíveis a partir do ponteiro do slice.
// Exemplo de declaração de um slice
var s []int
s = append(s, 1, 2, 3) // Adicionando elementos

// Representação interna do slice s (simplificada)
// struct SliceHeader {
//     Data uintptr // Ponteiro para o array base
//     Len int      // Comprimento do slice
//     Cap int      // Capacidade do slice
// }
  • Ao criar um slice com make([]T, length, capacity), um array base com a capacidade especificada é criado, e um slice que faz referência a ele com o comprimento indicado.
  • Ao usar uma fatia em um array ou outro slice (por exemplo, arr[low:high:max]), um novo slice é criado, que faz referência à mesma área de memória do array base, mas com ponteiros, comprimento e capacidade diferentes.
  • A operação append pode causar uma realocação de memória. Se a capacidade atual não for suficiente para adicionar novos elementos, o Go cria um novo array base maior, copia os elementos do antigo e atualiza o ponteiro do slice para o novo array. Isso é chamado de realocação. O crescimento da capacidade ao fazer append é exponencial (duplica até certo tamanho, depois desacelera).
  • Os slices são passados por valor, mas como eles contêm um ponteiro para o array base, as alterações nos elementos do slice (via índice) serão visíveis em todos os slices que fazem referência ao mesmo array.
  • Alterar o comprimento do slice por meio de uma fatia não afeta o array base, mas pode limitar o acesso a parte dos dados do array base.

Tabela: Comparação entre Length e Capacity

Característica Comprimento (Length) Capacidade (Capacity)
Definição Número real de elementos no slice Número máximo de elementos que o slice pode conter sem realocação
Acesso Usado para acessar os elementos (s[i]) Define quantos elementos adicionais podem ser adicionados com append antes da realocação
Obtenção len(s) cap(s)
// Exemplo de trabalho com capacidade e comprimento
s := make([]int, 0, 5) // Comprimento 0, capacidade 5
fmt.Println(len(s), cap(s)) // 0 5

s = append(s, 1, 2) // Adicionando 2 elementos
fmt.Println(len(s), cap(s)) // 2 5

s = append(s, 3, 4, 5, 6) // Adicionando mais 4 elementos, requer realocação
fmt.Println(len(s), cap(s)) // 6 10 (a capacidade aumentou)