Concatenação de strings em Go: como não matar a performance

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que a concatenação simples de strings em Go pode se tornar um problema?

\n\n

Todo mundo que começou a estudar Go, mais cedo ou mais tarde, se depara com a tarefa: precisa juntar várias strings em uma. A maneira mais óbvia é usar o operador += ou a simples adição +. E isso funciona… até você tentar juntar mil strings. De repente, seu código começa a ficar lento e a memória é gasta como na Black Friday.

\n\n

Por que isso acontece? Em Go, as strings são imutáveis (immutable). Quando você escreve s += "new", o Go não adiciona o texto ao final da string antiga. Ele cria uma nova string, copiando o conteúdo de ambas as partes. Em cada operação, nova memória é alocada. Se houver milhares dessas operações, o coletor de lixo começa a trabalhar em modo de emergência e a performance cai.

\n\n

Neste artigo, vamos analisar todas as formas de concatenação de strings em Go: desde as ingênuas até as industriais. Você aprenderá quando usar cada método e poderá escrever código que não seja vergonha mostrar em uma code review.

\n\n

Formas de concatenação de strings em Go: do simples ao eficiente

\n\n

Vamos considerar cinco abordagens principais. Para cada uma, darei um exemplo de código e explicarei em quais situações ela é adequada.

\n\n

1. Operador + e += (forma ingênua)

\n\n

O método mais simples e intuitivo. Ideal para juntar 2 a 5 strings.

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    hello := "Hello"\n    world := "World"\n    result := hello + ", " + world + "!"\n    fmt.Println(result) // Hello, World!\n}\n
\n\n

Quando usar: apenas para um pequeno número de strings. Se você estiver escrevendo um loop de 1000 iterações com += — pare. Isso é complexidade quadrática de memória (O(n²)).

\n\n

2. fmt.Sprintf

\n\n

Útil quando você precisa formatar a saída. Internamente, ele também cria novas strings, mas faz isso de forma mais eficiente do que a junção manual.

\n\n
name := "Alice"\nage := 30\nresult := fmt.Sprintf("My name is %s and I am %d years old.", name, age)\nfmt.Println(result)\n
\n\n

Quando usar: quando você precisa não apenas juntar, mas formatar uma string com diferentes tipos de dados. Para concatenação simples, não é a melhor escolha devido ao custo adicional de analisar o template.

\n\n

3. strings.Join — o rei para slices de strings

\n\n

Se você já tem um array ou slice de strings, strings.Join é a forma mais rápida e elegante.

\n\n
package main\n\nimport (\n    "fmt"\n    "strings"\n)\n\nfunc main() {\n    words := []string{"Go", "is", "awesome", "for", "backend"}\n    result := strings.Join(words, " ")\n    fmt.Println(result) // Go is awesome for backend\n}\n
\n\n

Internamente, strings.Join primeiro calcula o comprimento total do resultado, aloca memória uma vez e a preenche. Sem cópias desnecessárias.

\n\n

Quando usar: sempre que você tiver um slice de strings pronto. É a opção ideal para construir consultas SQL, strings CSV e URLs.

\n\n

4. bytes.Buffer — o clássico do gênero

\n\n

O pacote bytes fornece um buffer que cresce dinamicamente. Ele implementa a interface io.Writer, então você pode escrever nele através de WriteString.

\n\n
package main\n\nimport (\n    "bytes"\n    "fmt"\n)\n\nfunc main() {\n    var buffer bytes.Buffer\n\n    for i := 0; i < 5; i++ {\n        buffer.WriteString("Line ")\n        buffer.WriteString(fmt.Sprintf("%d\\n", i))\n    }\n\n    fmt.Println(buffer.String())\n}\n
\n\n

O buffer aloca memória em blocos (geralmente de 64 bytes), o que reduz significativamente o número de alocações em comparação com +=.

\n\n

Quando usar: em loops onde a quantidade de strings não é conhecida antecipadamente. Por exemplo, ao gerar HTML ou logs.

\n\n

5. strings.Builder — o padrão moderno (Go 1.10+)

\n\n

A partir do Go 1.10, surgiu um

Blogs

Book Recommendations