我有一个io.ReadCloser
对象(来自http.Response
个对象)。
将整个流转换为string
对象的最有效方法是什么?
答案 0 :(得分:154)
简短的回答是它效率不高,因为转换为字符串需要完整地复制字节数组。这是做你想做的事情的正确(非效率)方式:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
此副本作为保护机制完成。字符串是不可变的。如果您可以将[]字节转换为字符串,则可以更改字符串的内容。但是,go允许您使用不安全的软件包禁用类型安全机制。使用不安全的包裹需要您自担风险。希望这个名字是一个足够好的警告。以下是我将如何使用unsafe:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
我们走了,你现在已经有效地将你的字节数组转换为字符串。实际上,所有这一切都是欺骗类型系统将其称为字符串。这种方法有几点需要注意:
我的建议是坚持官方方法。复制不是 昂贵的,不值得不安全的邪恶。如果字符串太大而无法复制,则不应将其变为字符串。
答案 1 :(得分:88)
到目前为止,答案还没有解决问题的“整个流”部分。我认为这样做的好方法是ioutil.ReadAll
。使用名为io.ReaderCloser
的{{1}},我会写,
rc
答案 2 :(得分:5)
最有效的方法是始终使用[]byte
代替string
。
如果您需要打印从io.ReadCloser
收到的数据,fmt
包可以处理[]byte
,但效率不高,因为fmt
实施将在内部将[]byte
转换为string
。为了避免此转化,您可以为type ByteSlice []byte
类型实施fmt.Formatter
界面。
答案 3 :(得分:4)
data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))
答案 4 :(得分:1)
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
}
答案 5 :(得分:0)
我喜欢bytes.Buffer结构。我看到它有ReadFrom和String方法。我用[]字节但不是io.Reader。
答案 6 :(得分:0)
var b bytes.Buffer
b.ReadFrom(r)
// b.String()