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.Builder
bunu, temelin []byte
asla sızmamasını sağlayarak ve string
ileride 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.ReaderCloser
adlandı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, []byte
yerine her zaman kullanmak olacaktır string
.
Adresinden alınan verileri yazdırmanız gerektiğinde io.ReadCloser
, fmt
paket işleyebilir []byte
, ancak bu verimli değildir çünkü fmt
uygulama dahili []byte
olarak string
. Bu dönüşümü önlemek fmt.Formatter
için , arayüzü gibi bir tür için uygulayabilirsiniz type ByteSlice []byte
.
[]byte
a dönüştürme string
oldukça hızlıdır, ancak soru "en verimli yol" ile ilgiliydi. Şu anda, Go çalışma zamanı her zaman yeni bir tahsis edecek string
dönüştürürken []byte
için string
. Bunun nedeni, derleyicinin []byte
dö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.