在Go中,字符串是一种基本类型,这意味着它是只读的,对它的每次操作都会创建一个新字符串。
如果我想多次连接字符串而不知道结果字符串的长度,最好的方法是什么?
最天真的做法是:
var s string
for i := 0; i < 1000; i++ {
s += getShortStringFromSomewhere()
}
return s
但这似乎不是很有效。
在Go中,字符串是一种基本类型,这意味着它是只读的,对它的每次操作都会创建一个新字符串。
如果我想多次连接字符串而不知道结果字符串的长度,最好的方法是什么?
最天真的做法是:
var s string
for i := 0; i < 1000; i++ {
s += getShortStringFromSomewhere()
}
return s
但这似乎不是很有效。
当前回答
扩展cd1的答案: 你可以使用append()而不是copy()。 Append()提供了更大的预先准备,占用了更多的内存,但节省了时间。 我在你的上面又加了两个基准测试。 在本地运行
go test -bench=. -benchtime=100ms
在我的thinkpad T400s上,它产生:
BenchmarkAppendEmpty 50000000 5.0 ns/op
BenchmarkAppendPrealloc 50000000 3.5 ns/op
BenchmarkCopy 20000000 10.2 ns/op
其他回答
goutils。JoinBetween
func JoinBetween(in []string, separator string, startIndex, endIndex int) string {
if in == nil {
return ""
}
noOfItems := endIndex - startIndex
if noOfItems <= 0 {
return EMPTY
}
var builder strings.Builder
for i := startIndex; i < endIndex; i++ {
if i > startIndex {
builder.WriteString(separator)
}
builder.WriteString(in[i])
}
return builder.String()
}
这是最快的解决方案,不需要 你首先需要知道或计算总的缓冲区大小:
var data []byte
for i := 0; i < 1000; i++ {
data = append(data, getShortStringFromSomewhere()...)
}
return string(data)
根据我的基准测试,它比复制解决方案慢了20% (8.1ns / 追加而不是6.72ns),但仍然比使用bytes.Buffer快55%。
我使用以下方法:-
package main
import (
"fmt"
"strings"
)
func main (){
concatenation:= strings.Join([]string{"a","b","c"},"") //where second parameter is a separator.
fmt.Println(concatenation) //abc
}
扩展cd1的答案: 你可以使用append()而不是copy()。 Append()提供了更大的预先准备,占用了更多的内存,但节省了时间。 我在你的上面又加了两个基准测试。 在本地运行
go test -bench=. -benchtime=100ms
在我的thinkpad T400s上,它产生:
BenchmarkAppendEmpty 50000000 5.0 ns/op
BenchmarkAppendPrealloc 50000000 3.5 ns/op
BenchmarkCopy 20000000 10.2 ns/op
package main
import (
"fmt"
)
func main() {
var str1 = "string1"
var str2 = "string2"
result := make([]byte, 0)
result = append(result, []byte(str1)...)
result = append(result, []byte(str2)...)
result = append(result, []byte(str1)...)
result = append(result, []byte(str2)...)
fmt.Println(string(result))
}