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.Builder
melakukan ini secara efisien dengan memastikan bahwa yang mendasarinya []byte
tidak pernah bocor, dan mengubahnya menjadi string
tanpa 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.ReaderCloser
nama 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 []byte
bukannyastring
.
Dalam kasus Anda perlu untuk mencetak data yang diterima dari io.ReadCloser
, yang fmt
paket dapat menangani []byte
, tetapi tidak efisien karena fmt
pelaksanaan internal akan mengkonversi []byte
ke string
. Untuk menghindari konversi ini, Anda dapat mengimplementasikan fmt.Formatter
antarmuka untuk jenis suka type ByteSlice []byte
.
[]byte
ke string
cukup cepat, tetapi pertanyaannya adalah tentang "cara paling efisien". Saat ini, Go run-time akan selalu mengalokasikan yang baru string
saat dikonversi []byte
ke string
. Alasan untuk ini adalah bahwa kompiler tidak tahu bagaimana menentukan apakah []byte
akan 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.