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。