Médio Go
Fatiando e observando o aliasing
Enunciado
Dado nums := []int{1, 2, 3, 4, 5}, crie um sub-slice sub := nums[1:4] e imprima nums, sub e o cap(sub). Depois altere sub[0] = 99 e imprima nums novamente para mostrar o compartilhamento.
Requisitos
- Criar o slice original com 5 inteiros.
- Criar
subusando fatiamentonums[1:4]. - Imprimir
cap(sub)(deve ser 4). - Mostrar que alterar
sub[0]mudanums[1].
Código inicial
package main
import "fmt"
func main() {
nums := []int{1, 2, 3, 4, 5}
// TODO: crie sub, imprima tudo e altere sub[0]
}
Saída esperada
nums=[1 2 3 4 5] sub=[2 3 4] cap(sub)=4
após alterar: nums=[1 99 3 4 5] sub=[99 3 4]
Ver dica
nums[1:4] pega os índices 1, 2 e 3. A capacidade vai do índice inicial até o fim do array subjacente.
Mostrar solução
package main
import "fmt"
func main() {
nums := []int{1, 2, 3, 4, 5}
// sub enxerga os índices 1..3 do mesmo array de nums
sub := nums[1:4]
fmt.Printf("nums=%v sub=%v cap(sub)=%d\n", nums, sub, cap(sub))
// sub[0] é o mesmo elemento que nums[1]
sub[0] = 99
fmt.Printf("após alterar: nums=%v sub=%v\n", nums, sub)
}
Passo a passo
numsé um slice de 5 inteiros; o compilador cria um array subjacente com esses valores.nums[1:4]cria um novo slice que aponta para o elemento de índice 1 do array, comlen=3(índices 1, 2, 3).cap(sub)é 4 porque, a partir do índice 1, ainda existem 4 posições até o fim do array (índices 1, 2, 3, 4).- O primeiro
Printfmostra os dois slices e a capacidade. sub[0] = 99escreve na posição quenumsenxerga como índice 1, entãonums[1]vira 99.- O segundo
Printfconfirma que os dois slices refletem a mudança.
Por que funciona
Fatiar não copia dados: cria um novo cabeçalho (ponteiro, len, cap) sobre o mesmo backing array. Por isso alterações em elementos compartilhados aparecem nos dois slices. É o famoso aliasing.
Erros comuns
- Achar que
sub := nums[1:4]copiou os valores: não copiou, é uma visão. - Esperar
cap(sub) == len(sub): a capacidade vai até o fim do array, não até o fim do slice. - Tentar acessar
sub[3]:len(sub)é 3, então o índice válido vai só até 2, mesmo comcap=4.
Outra forma de resolver
Se você quiser uma cópia independente, use slices.Clone (Go 1.21+):
sub := slices.Clone(nums[1:4])
sub[0] = 99 // não afeta nums
Prefira cópia quando for modificar sem querer afetar o original.
Saída esperada
nums=[1 2 3 4 5] sub=[2 3 4] cap(sub)=4
após alterar: nums=[1 99 3 4 5] sub=[99 3 4]