如何在Go中有效地串联字符串

在Go中,astring是一种原始类型,这意味着它是只读的,对其的每次操作都会创建一个新的字符串。


因此,如果我想多次连接字符串而又不知道结果字符串的长度,那么最好的方法是什么?


天真的方法是:


var s string

for i := 0; i < 1000; i++ {

    s += getShortStringFromSomewhere()

}

return s

但这似乎不是很有效。


慕后森
浏览 221回答 3
3回答

POPMUISE

新的方法:从Go 1.10开始,有一种strings.Builder类型,请查看此答案以获取更多详细信息。旧方法:使用bytes包装。它具有Buffer实现的类型io.Writer。package mainimport (&nbsp; &nbsp; "bytes"&nbsp; &nbsp; "fmt")func main() {&nbsp; &nbsp; var buffer bytes.Buffer&nbsp; &nbsp; for i := 0; i < 1000; i++ {&nbsp; &nbsp; &nbsp; &nbsp; buffer.WriteString("a")&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println(buffer.String())}这是在O(n)时间内完成的。

慕神8447489

在Go 1.10+中strings.Builder,这里是。生成器用于使用Write方法有效地构建字符串。它最大程度地减少了内存复制。零值可以使用了。例子与几乎相同bytes.Buffer。package mainimport (&nbsp; &nbsp; "strings"&nbsp; &nbsp; "fmt")func main() {&nbsp; &nbsp; // ZERO-VALUE:&nbsp; &nbsp; //&nbsp; &nbsp; // It's ready to use from the get-go.&nbsp; &nbsp; // You don't need to initialize it.&nbsp; &nbsp; var sb strings.Builder&nbsp; &nbsp; for i := 0; i < 1000; i++ {&nbsp; &nbsp; &nbsp; &nbsp; sb.WriteString("a")&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println(sb.String())}支持的接口正在考虑现有接口的情况下实现StringBuilder的方法。这样您就可以在代码中轻松切换到新的Builder类型。Grow(int)->&nbsp;bytes.Buffer#GrowLen()int-&nbsp;>&nbsp;bytes.Buffer#LenReset()->&nbsp;bytes.Buffer#ResetString()字符串->&nbsp;fmt.StringerWrite([] byte)(int,error)->&nbsp;io.WriterWriteByte(byte)错误->&nbsp;io.ByteWriterWriteRune(rune)(int,error)->&nbsp;bufio.Writer#WriteRune&nbsp;-&nbsp;bytes.Buffer#WriteRuneWriteString(string)(int,error)->&nbsp;io.stringWriter与bytes.Buffer的差异它只能增长或重置。它具有内置的copyCheck机制,可防止意外复制它:func (b *Builder) copyCheck() { ... }在中bytes.Buffer,您可以像这样访问基础字节:(*Buffer).Bytes()。strings.Builder&nbsp;可以防止此问题。有时,这不是问题,而是需要的。例如:对于将字节传递给io.Readeretc时的偷窥行为。bytes.Buffer.Reset()&nbsp;倒带并重用基础缓冲区,而strings.Builder.Reset()&nbsp;not则分离缓冲区。笔记不要复制StringBuilder值,因为它会缓存基础数据。如果要共享StringBuilder值,请使用指向它的指针。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go