Eu tenho um io.ReadCloser
objeto (de um http.Response
objeto).
Qual é a maneira mais eficiente de converter todo o fluxo em um string
objeto?
EDITAR:
Desde a versão 1.10, existe o strings.Builder. Exemplo:
buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.String())
INFORMAÇÃO ATUALIZADA ABAIXO
A resposta curta é que não será eficiente, pois a conversão para uma string exige uma cópia completa da matriz de bytes. Aqui está a maneira correta (não eficiente) de fazer o que você deseja:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
Esta cópia é feita como um mecanismo de proteção. Strings são imutáveis. Se você pudesse converter um byte [] em uma string, poderia alterar o conteúdo da string. No entanto, o go permite desativar os mecanismos de segurança de tipo usando o pacote não seguro. Use o pacote não seguro por sua conta e risco. Espero que o nome por si só seja um aviso suficientemente bom. Aqui está como eu faria isso usando inseguro:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
Lá vamos nós, agora você converteu eficientemente sua matriz de bytes em uma string. Realmente, tudo o que isso faz é induzir o sistema de tipos a chamá-lo de string. Existem algumas ressalvas nesse método:
Meu conselho é seguir o método oficial. Fazendo uma cópia não é que caro e não vale a pena os males do inseguro. Se a sequência for muito grande para fazer uma cópia, você não deve transformá-la em uma sequência.
strings.Builder
faz isso de maneira eficiente, garantindo que o subjacente[]byte
nunca vaze e convertendo parastring
sem uma cópia de uma maneira que seja suportada no futuro. Isso não existia em 2012. A solução da @ dimchansky abaixo foi a correta desde o Go 1.10. Considere uma edição!Até agora, as respostas não abordaram a parte "stream inteiro" da pergunta. Eu acho que a boa maneira de fazer isso é
ioutil.ReadAll
. Com o seuio.ReaderCloser
nomerc
, eu escreveria,fonte
buf.ReadFrom()
também lê todo o fluxo até o EOF.ioutil.ReadAll()
e simplesmente envolve umbytes.Buffer
'sReadFrom
. E oString()
método do buffer é uma quebra simples da conversão parastring
- portanto, as duas abordagens são praticamente as mesmas!fonte
A maneira mais eficiente seria sempre usar em
[]byte
vez destring
.Caso você precise imprimir dados recebidos do
io.ReadCloser
, ofmt
pacote pode manipular[]byte
, mas não é eficiente porque afmt
implementação será convertida internamente[]byte
emstring
. Para evitar essa conversão, você pode implementar afmt.Formatter
interface para um tipo comotype ByteSlice []byte
.fonte
[]byte
parastring
é razoavelmente rápida, mas a pergunta estava sendo feita "da maneira mais eficiente". Atualmente, o tempo de execução Go sempre aloca um novostring
ao converter[]byte
parastring
. A razão para isso é que o compilador não sabe como determinar se o[]byte
será modificado após a conversão. Há espaço para otimizações do compilador aqui.fonte
fonte
Eu gosto da estrutura bytes.Buffer . Eu vejo que ele tem métodos ReadFrom e String . Eu usei com um byte [], mas não com um io.Reader.
fonte