Nesse post vamos ver 3 formas diferentes de aumentar o tamanho de um array em Go.
Para ficar um pouco mais interessante, vamos trabalhar com 2 arrays. O primeiro será um array de string e o segundo um array de Pessoa.
type Pessoa struct { Nome string Idade int32 }
Primeira forma é também a mais simples. Particularmente, eu tento evitar ao máximo utilizar esse método para aumentar meus arrays, pois embora ela seja a mais simples, é também a mais custosa.
nomes := []string{"Tiago", "Alexandre", "Luara"} pessoas := []Pessoa{ {Nome: "Dani", Idade: 35}, {Nome: "Lucas", Idade: 29}, {Nome: "Rafael", Idade: 38}, } for _, pessoa := range pessoas { nomes = append(nomes, pessoa.Nome) }
Como nós já discutimos em outro post (click aqui para ler), essa abordagem faz com que o Go aumente o array nomes uma posição por vez, o que pode custar muito em relação a processamento e memória.
Segunda forma que vamos abordar, é criando um novo array com o tamanho 0 e capacidade 6.
nomes := []string{"Tiago", "Alexandre", "Luara"} pessoas := []Pessoa{ {Nome: "Dani", Idade: 35}, {Nome: "Lucas", Idade: 29}, {Nome: "Rafael", Idade: 38}, } todos := make([]string, 0, len(nomes) + len(pessoas)) for _, nome := range nomes { todos = append(todos, nome) } for _, pessoa := range pessoas { todos = append(todos, pessoa.Nome) }
Embora esse código seja mais extenso, ele garante que não seja necessário realocação do array, já que o criamos com a capacidade necessária desde o inicio. Nesse caso acabamos não aumentando o tamanho de um array, mas sim criando um novo. O lado ruim dessa abordagem é que, ao final da execução teremos 3 arrays ocupando 12 posições na memória.
Na terceira forma, assim como na primeira, vamos expandir o array nomes, mas de uma forma um pouco diferente.
nomes := []string{"Tiago", "Alexandre", "Luara"} pessoas := []Pessoa{ {Nome: "Dani", Idade: 35}, {Nome: "Lucas", Idade: 29}, {Nome: "Rafael", Idade: 38}, } // o tamanho do array é a posição seguinte index := len(nomes) nomes = append(nomes, make([]string, len(pessoas))...) for _, pessoa := range pessoas { nomes[index] = pessoa.Nome index++ }
Nesse último exemplo, criamos um array de string com o tamanho do array pessoas e fazemos o append ao array nomes. A diferença dele para o primeiro é que, como criamos um array vazio e passamos os itens como parâmetro do append, o Go só vai realocar o array 1 vez, pois já sabe que precisa aumentar o array nomes em 3 posições.
Mas afinal, qual dessas abordagens tem melhor performance????
Nos primeiros testes que fiz, usando 2 arrays com 3 posições cada, a diferença não foi muito grande. Por isso resolvi fazer um segundo teste usando o array nomes com 3 posições e o pessoas com 30.
Para o benchmark, executei o seguinte comando:
go test -bench="NomeFunc" -cpu=8 -benchmem -benchtime=5s -count 5 -memprofile=mem.out
Primeira forma

Segunda forma

Terceira forma

Como podemos ver, a terceira forma é sem dúvida a melhor opção, pois tem seus números muito parecidos com a segunda (que é a segunda melhor opção), porém um consumo de memória é 18% menor.
Deixem suas dúvidas nos comentários.
Até a próxima!
Bom dia Tiago, blz? Uma dúvida, no método 1, você fala que o Go aumenta a posição do array uma por vez.
Quando o slice chega ao limite, a função append não dobra esse limite? Em teoria ao inserir o 4º valor, a capacidade não seria 6?
Ele aumenta o tamanho em 1 e dobra a capacidade.