[英]From io.Reader to string in Go
我有一個io.ReadCloser
對象(來自http.Response
對象)。
將整個流轉換為string
對象的最有效方法是什么?
編輯:
從 1.10 開始,strings.Builder 就存在了。 例子:
buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.String())
以下過時信息
簡短的回答是它效率不高,因為轉換為字符串需要對字節數組進行完整的復制。 這是做你想做的正確(非有效)的方法:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
此副本是作為保護機制完成的。 字符串是不可變的。 如果可以將 []byte 轉換為字符串,則可以更改字符串的內容。 但是,go 允許您使用 unsafe 包禁用類型安全機制。 使用 unsafe 包的風險由您自己承擔。 希望這個名字本身就是一個足夠好的警告。 這是我將如何使用 unsafe 來做到這一點:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
好了,您現在已經有效地將字節數組轉換為字符串。 實際上,所有這些都是欺騙類型系統將其稱為字符串。 這種方法有幾個注意事項:
我的建議是堅持官方的方法。 做一個副本並不那么昂貴,也不值得不安全的罪惡。 如果字符串太大而無法復制,則不應將其制作成字符串。
到目前為止,答案還沒有解決問題的“整個流”部分。 我認為這樣做的好方法是ioutil.ReadAll
。 使用名為rc
的io.ReaderCloser
,我會寫,
去>= v1.16
if b, err := io.ReadAll(rc); err == nil {
return string(b)
} ...
去 <= v1.15
if b, err := ioutil.ReadAll(rc); err == nil {
return string(b)
} ...
data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))
最有效的方法是始終使用[]byte
而不是string
。
如果您需要打印從io.ReadCloser
接收到的io.ReadCloser
, fmt
包可以處理[]byte
,但效率不高,因為fmt
實現會在內部將[]byte
轉換為string
。 為了避免這種轉換,您可以為類似type ByteSlice []byte
的類型實現fmt.Formatter
接口。
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()
我喜歡bytes.Buffer結構。 我看到它有ReadFrom和String方法。 我已經將它與 []byte 一起使用,但沒有與 io.Reader 一起使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.