Como converter um array de bytes com caractere nulo em string em Go

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

Introdução: quando os bytes se calam e a string não se forma



Imagine: você escreveu um servidor em Go que recebe dados de uma biblioteca em C. Ou está analisando um protocolo binário onde as strings são armazenadas no bom e velho estilo C — com um byte nulo de terminação (\\0). Você tenta simplesmente fazer string(byteArray) e obtém… lixo. Ou, pior ainda, bugs ocultos que aparecerão daqui a um mês em produção.



Familiar? Esta pergunta no Stack Overflow acumulou milhares de visualizações por um motivo. O problema de converter um zero-terminated byte array em string é um daqueles que quebram lanças até mesmo entre desenvolvedores Go experientes. Neste artigo, vamos analisá-lo do início ao fim: desde a solução simples até as armadilhas de desempenho, memória e Unicode.



Se você programa em Go e trabalha com arrays de bytes, CGO ou protocolos de rede — este artigo é para você. Vamos nessa!



O que é um zero-terminated byte array e por que é um problema em Go?



Zero-terminated byte array (ou null-terminated string) é um array de bytes cujo final é marcado por um byte nulo (0x00). É um legado da linguagem C, onde as strings são exatamente assim: um array de char terminado por \\0.



Em Go, strings são sequências imutáveis de bytes de comprimento arbitrário. O byte nulo dentro de uma string é um caractere comum, não indica o fim. Portanto, a conversão direta string([]byte{104, 101, 108, 108, 111, 0, 119, 111, 114, 108, 100}) resultará na string "hello\\x00world", e não em "hello".



É aqui que está a principal armadilha: se você simplesmente copiar os bytes, o caractere nulo permanecerá dentro da string. Isso pode levar a:

  • Exibição incorreta em logs e interfaces de usuário
  • Erros durante a serialização (JSON, XML)
  • Problemas com hash e comparação de strings
  • Vazamento de dados, se a string contiver informações confidenciais após o nulo


Solução nº 1: Método clássico com bytes.IndexByte



A maneira mais simples e clara é encontrar a posição do primeiro byte nulo e truncar o array até ele. Para isso, a função bytes.IndexByte da biblioteca padrão é ideal.



package main

import ( "bytes" "fmt")

func zeroTerminatedToString(data []byte) string { // Encontra o índice do primeiro byte nulo idx := bytes.IndexByte(data, 0) if idx == -1 { // Se não houver byte nulo — retorna tudo como está return string(data) } // Trunca o array até o índice encontrado return string(data[:idx])}

func main() { // Exemplo: string C "hello" com terminador nulo cArray := []byte{'h', 'e', 'l', 'l', 'o', 0, 'e', 'x', 't', 'r', 'a'} result := zeroTerminatedToString(cArray) fmt.Printf("Resultado: %q", result) // "hello" fmt.Printf("Comprimento: %d", len(result)) // 5}


Este código é rápido, fácil de ler e cobre 80% dos cenários. Mas há um detalhe: bytes.IndexByte percorre todo o array até o primeiro nulo. Se o array for enorme e o byte nulo estiver no final — é uma operação O(n).



Quando esta solução não é adequada?

  • Se o array garantir ter um byte nulo no início (string vazia) — precisa ser tratado separadamente
  • Se o desempenho for crítico e você chamar esta função milhões de vezes
  • Se os dados contiverem vários bytes nulos (por exemplo, um array de strings C)


Solução nº 2: Usando CGO e funções C (para os corajosos)



Se você trabalha diretamente com código C via CGO, pode chamar a função C padrão strlen. Isso é elegante, mas adiciona dependência de CGO e custos indiretos de chamada.



// #include <string.h>import "C"import "unsafe"

func cStringToString(cArray []byte) string { if len(

Blogs

Book Recommendations