Risposte:
MODIFICARE:
Dall'1.10, stringhe.Builder esiste. Esempio:
buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.String())
INFORMAZIONI SUCCESSIVE SOTTO
La risposta breve è che non sarà efficiente perché la conversione in una stringa richiede una copia completa dell'array di byte. Ecco il modo corretto (non efficiente) di fare ciò che vuoi:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
Questa copia viene eseguita come meccanismo di protezione. Le stringhe sono immutabili. Se fosse possibile convertire un byte [] in una stringa, è possibile modificare il contenuto della stringa. Tuttavia, go consente di disabilitare i meccanismi di sicurezza del tipo utilizzando il pacchetto non sicuro. Utilizzare il pacchetto non sicuro a proprio rischio. Speriamo che solo il nome sia un avvertimento abbastanza buono. Ecco come lo farei usando non sicuro:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
Eccoci, ora hai convertito in modo efficiente il tuo array di byte in una stringa. In realtà, tutto ciò che fa è ingannare il sistema dei tipi nel chiamarlo stringa. Ci sono un paio di avvertenze su questo metodo:
Il mio consiglio è di attenersi al metodo ufficiale. Fare una copia non è così costoso e non vale i mali dei non sicuri. Se la stringa è troppo grande per fare una copia, non dovresti trasformarla in una stringa.
strings.Builderlo fa in modo efficiente garantendo che il sottostante []bytenon perda mai e convertendosi stringsenza una copia in un modo che sarà supportato in futuro. Questo non esisteva nel 2012. La soluzione di @ dimchansky sotto è stata quella corretta da Go 1.10. Si prega di considerare una modifica!
Finora le risposte non hanno affrontato la parte "intero flusso" della domanda. Penso che il buon modo per farlo sia ioutil.ReadAll. Con il tuo io.ReaderClosernome rc, scriverei,
if b, err := ioutil.ReadAll(rc); err == nil {
return string(b)
} ...
buf.ReadFrom()anche leggere l'intero flusso fino a EOF.
ioutil.ReadAll()e semplicemente avvolge un bytes.Buffer's ReadFrom. E il String()metodo del buffer è un semplice giro attorno al casting string, quindi i due approcci sono praticamente gli stessi!
data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))
Il modo più efficiente sarebbe usare sempre []byteinvece di string.
In caso di necessità di stampare i dati ricevuti dal io.ReadCloser, il fmtpacchetto in grado di gestire []byte, ma non è efficace perché l' fmtattuazione internamente la conversione []bytea string. Al fine di evitare questa conversione, è possibile implementare l' fmt.Formatterinterfaccia per un tipo simile type ByteSlice []byte.
[]bytea stringè ragionevolmente veloce, ma la domanda era "il modo più efficiente". Attualmente, il runtime di Go assegnerà sempre un nuovo stringdurante la conversione []bytein string. La ragione di ciò è che il compilatore non sa come determinare se []byteverrà modificato dopo la conversione. C'è spazio per le ottimizzazioni del compilatore qui.
func copyToString(r io.Reader) (res string, err error) {
var sb strings.Builder
if _, err = io.Copy(&sb, r); err == nil {
res = sb.String()
}
return
}
var b bytes.Buffer
b.ReadFrom(r)
// b.String()
Mi piacciono i byte.Buffer struct. Vedo che ha i metodi ReadFrom e String . L'ho usato con un byte [] ma non con un io.Reader.