Saya punya io.ReadCloser
objek (dari http.Response
objek).
Apa cara paling efisien untuk mengubah seluruh aliran menjadi string
objek?
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 menjadistring
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
. Denganio.ReaderCloser
nama Andarc
, saya akan menulis,sumber
buf.ReadFrom()
juga membaca seluruh aliran hingga EOF.ioutil.ReadAll()
dan itu hanya membungkusbytes.Buffer
'sReadFrom
. Dan metode bufferString()
adalah membungkus casting yang sederhanastring
- sehingga kedua pendekatannya praktis sama!sumber
Cara yang paling efisien akan selalu menggunakan
[]byte
bukannyastring
.Dalam kasus Anda perlu untuk mencetak data yang diterima dari
io.ReadCloser
, yangfmt
paket dapat menangani[]byte
, tetapi tidak efisien karenafmt
pelaksanaan internal akan mengkonversi[]byte
kestring
. Untuk menghindari konversi ini, Anda dapat mengimplementasikanfmt.Formatter
antarmuka untuk jenis sukatype ByteSlice []byte
.sumber
[]byte
kestring
cukup cepat, tetapi pertanyaannya adalah tentang "cara paling efisien". Saat ini, Go run-time akan selalu mengalokasikan yang barustring
saat dikonversi[]byte
kestring
. Alasan untuk ini adalah bahwa kompiler tidak tahu bagaimana menentukan apakah[]byte
akan dimodifikasi setelah konversi. Ada beberapa ruang untuk optimisasi kompiler di sini.sumber
sumber
Saya suka struct bytes.Buffer . Saya melihatnya memiliki metode ReadFrom dan String . Saya telah menggunakannya dengan byte [] tetapi bukan io.Reader.
sumber