Answers:
编辑:
从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软件包禁用类型安全机制。使用不安全的包装,后果自负。希望仅此名称就足够了。这是我使用不安全方法的方法:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
到此为止,您现在已经有效地将字节数组转换为字符串。确实,所有这些都是在欺骗类型系统将其称为字符串。此方法有两个警告:
我的建议是坚持官方方法。进行复制并没有那么昂贵,而且不值得进行不安全的弊端。如果字符串太大而无法进行复制,则不应将其制成字符串。
strings.Builder通过确保底层[]byte永不泄漏并以string支持将来的方式转换为无副本,从而有效地做到了这一点。这在2012年不存在。@dimchansky的以下解决方案自Go 1.10起就是正确的解决方案。请考虑修改!
到目前为止,答案还没有解决问题的“整个流”部分。我认为这样做的好方法是ioutil.ReadAll。用你的io.ReaderCloser名字rc,我会写,
if b, err := ioutil.ReadAll(rc); err == nil {
return string(b)
} ...
buf.ReadFrom()还读取了整个流,直至达到EOF。
ioutil.ReadAll()它只是包装bytes.Buffer的ReadFrom。而且缓冲区的String()方法是将对象强制转换为简单包装的方法string-因此这两种方法实际上是相同的!
最有效的方法是始终使用[]byte而不是string。
如果您需要打印从接收到的数据io.ReadCloser,该fmt包可以处理[]byte,但效率不高,因为fmt实现会在内部转换[]byte为string。为了避免这种转换,您可以fmt.Formatter为类型的类型实现接口type ByteSlice []byte。
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方法。我已经使用了[]字节,但未使用io.Reader。