Yanıtlar:
DÜZENLE:
1.10'dan beri string.Builder var. Misal:
buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.String())
AŞAĞIDAKİ GEÇMİŞ BİLGİLER
Kısa cevap, bunun verimli olmayacağıdır çünkü bir dizgeye dönüştürmek, bayt dizisinin tam bir kopyasını yapmayı gerektirir. İstediğinizi yapmanın doğru (verimli olmayan) yolu:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
Bu kopya bir koruma mekanizması olarak yapılır. Dizeler değişmezdir. Bir [] baytı bir dizgeye dönüştürebilseydiniz, dizenin içeriğini değiştirebilirsiniz. Bununla birlikte, go, güvenli olmayan paketi kullanarak tür güvenlik mekanizmalarını devre dışı bırakmanıza izin verir. Güvenli olmayan paketi kullanma riski size aittir. Umarım tek başına isim yeterince iyi bir uyarıdır. Güvensiz kullanarak bunu şu şekilde yapardım:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
İşte başlıyoruz, şimdi bayt dizinizi verimli bir şekilde bir dizeye dönüştürdünüz. Gerçekte, tüm bunlar tip sistemini kandırarak onu bir dizge olarak adlandırmaktır. Bu yönteme ilişkin birkaç uyarı vardır:
Benim tavsiyem resmi yönteme bağlı kalmaktır. Bir kopya yapmak o kadar pahalı değil ve güvensizliğin kötülüklerine değmez. Dize bir kopya yapmak için çok büyükse, onu bir dizeye dönüştürmemelisiniz.
strings.Builderbunu, temelin []byteasla sızmamasını sağlayarak ve stringileride desteklenecek bir şekilde kopyasız hale getirerek verimli bir şekilde yapar. Bu 2012'de yoktu. @ Dimchansky'nin aşağıdaki çözümü, 1.10'dan beri doğru olanıydı. Lütfen bir düzenleme yapmayı düşünün!
Şimdiye kadar verilen yanıtlar, sorunun "tüm akış" kısmına değinmedi. Sanırım bunu yapmanın en iyi yolu ioutil.ReadAll. Senin ile io.ReaderCloseradlandırılmış rc, ben yazardım,
if b, err := ioutil.ReadAll(rc); err == nil {
return string(b)
} ...
buf.ReadFrom()zamanda EOF'ye kadar tüm akışı okuyor gibi görünüyor .
ioutil.ReadAll()ve basitçe a bytes.Buffer' yı sarıyor ReadFrom. Ve tamponun String()yöntemi, dökümün etrafında basit bir sarmadır string- bu nedenle iki yaklaşım pratikte aynıdır!
data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))
En verimli yol, []byteyerine her zaman kullanmak olacaktır string.
Adresinden alınan verileri yazdırmanız gerektiğinde io.ReadCloser, fmtpaket işleyebilir []byte, ancak bu verimli değildir çünkü fmtuygulama dahili []byteolarak string. Bu dönüşümü önlemek fmt.Formatteriçin , arayüzü gibi bir tür için uygulayabilirsiniz type ByteSlice []byte.
[]bytea dönüştürme stringoldukça hızlıdır, ancak soru "en verimli yol" ile ilgiliydi. Şu anda, Go çalışma zamanı her zaman yeni bir tahsis edecek stringdönüştürürken []byteiçin string. Bunun nedeni, derleyicinin []bytedönüşümden sonra değiştirilip değiştirilmeyeceğini nasıl belirleyeceğini bilmemesidir . Derleyici optimizasyonları için burada biraz yer var.
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()
Sevdiğim bytes.Buffer yapı. ReadFrom ve String yöntemlerine sahip olduğunu görüyorum . Bunu bir [] bayt ile kullandım ama bir io.Reader ile değil.