Jawaban:
EDIT:
Sejak 1,10, strings.Builder ada. Contoh:
buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.String())
INFORMASI KEDUA DI BAWAH
Jawaban singkatnya adalah bahwa itu tidak akan efisien karena mengkonversi ke string memerlukan melakukan salinan array byte lengkap. Inilah cara yang tepat (tidak efisien) untuk melakukan apa yang Anda inginkan:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
Salinan ini dilakukan sebagai mekanisme perlindungan. String tidak berubah. Jika Anda bisa mengonversi byte [] menjadi string, Anda bisa mengubah konten string. Namun, go memungkinkan Anda untuk menonaktifkan jenis mekanisme keamanan menggunakan paket yang tidak aman. Gunakan paket yang tidak aman dengan risiko Anda sendiri. Semoga saja nama itu peringatan yang cukup bagus. Inilah cara saya melakukannya menggunakan tidak aman:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
Ini dia, Anda sekarang telah secara efisien mengkonversi byte array Anda menjadi sebuah string. Sungguh, semua ini dilakukan adalah mengelabui sistem tipe agar menyebutnya string. Ada beberapa peringatan untuk metode ini:
Saran saya adalah tetap berpegang pada metode resmi. Melakukan salinan tidak yang mahal dan tidak sebanding dengan kejahatan yang tidak aman. Jika string terlalu besar untuk dikopi, Anda tidak boleh membuatnya menjadi string.
strings.Buildermelakukan ini secara efisien dengan memastikan bahwa yang mendasarinya []bytetidak pernah bocor, dan mengubahnya menjadi stringtanpa salinan dengan cara yang akan didukung di masa mendatang. Ini tidak ada pada 2012. Solusi @ dimchansky di bawah ini adalah yang benar sejak Go 1.10. Silakan pertimbangkan hasil edit!
Jawaban sejauh ini belum membahas bagian "seluruh aliran" dari pertanyaan. Saya pikir cara terbaik untuk melakukan ini adalah ioutil.ReadAll. Dengan io.ReaderClosernama Anda rc, saya akan menulis,
if b, err := ioutil.ReadAll(rc); err == nil {
return string(b)
} ...
buf.ReadFrom()juga membaca seluruh aliran hingga EOF.
ioutil.ReadAll()dan itu hanya membungkus bytes.Buffer's ReadFrom. Dan metode buffer String()adalah membungkus casting yang sederhana string- sehingga kedua pendekatannya praktis sama!
data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))
Cara yang paling efisien akan selalu menggunakan []bytebukannyastring .
Dalam kasus Anda perlu untuk mencetak data yang diterima dari io.ReadCloser, yang fmtpaket dapat menangani []byte, tetapi tidak efisien karena fmtpelaksanaan internal akan mengkonversi []byteke string. Untuk menghindari konversi ini, Anda dapat mengimplementasikan fmt.Formatterantarmuka untuk jenis suka type ByteSlice []byte.
[]byteke stringcukup cepat, tetapi pertanyaannya adalah tentang "cara paling efisien". Saat ini, Go run-time akan selalu mengalokasikan yang baru stringsaat dikonversi []byteke string. Alasan untuk ini adalah bahwa kompiler tidak tahu bagaimana menentukan apakah []byteakan dimodifikasi setelah konversi. Ada beberapa ruang untuk optimisasi kompiler di sini.
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()
Saya suka struct bytes.Buffer . Saya melihatnya memiliki metode ReadFrom dan String . Saya telah menggunakannya dengan byte [] tetapi bukan io.Reader.