大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
以下五个字符串连接函数,你认为哪一个最快?
目前创新互联公司已为数千家的企业提供了网站建设、域名、网络空间、网站改版维护、企业网站设计、疏附网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
func StrConcat1(strs []string) (string) {
var str string
for _, value := range strs {
str += value
}
return str
}
func StrConcat2(strs []string) (string) {
if len(strs) == 0 {
return ""
}
b := bytes.Buffer{}
for _, s := range strs {
b.WriteString(s)
}
return b.String()
}
func StrConcat3(strs []string) (string) {
return strings.Join(strs, "")
}
func StrConcat4(strs []string) (string) {
var data []byte
for _, value := range strs {
data = append(data, value...)
}
return string(data)
}
func StrConcat5(strs []string) (string) {
var length int
for _, s := range strs {
length += len(s)
}
bs := make([]byte, length)
var i int
for _, value := range strs {
i += copy(bs[i:], value)
}
return string(bs[:])
}
编写如下的测试文件
import "testing"
var TestStr = []string{"hello", "world", "my", "god", "this", "is", "big", "content"}
func Benchmark_StrConcat1(b *testing.B) {
for i := 0; i < b.N ; i++ {
StrConcat1(TestStr)
}
}
func Benchmark_StrConcat2(b *testing.B) {
for i := 0; i < b.N ; i++ {
StrConcat2(TestStr)
}
}
func Benchmark_StrConcat3(b *testing.B) {
for i := 0; i < b.N ; i++ {
StrConcat3(TestStr)
}
}
func Benchmark_StrConcat4(b *testing.B) {
for i := 0; i < b.N ; i++ {
StrConcat4(TestStr)
}
}
func Benchmark_StrConcat5(b *testing.B) {
for i := 0; i < b.N ; i++ {
StrConcat5(TestStr)
}
}
然后执行测试命令
go test -test.bench=".*"
执行结果如下:
Benchmark_StrConcat1-4 5000000 366 ns/op
Benchmark_StrConcat2-4 10000000 178 ns/op
Benchmark_StrConcat3-4 10000000 127 ns/op
Benchmark_StrConcat4-4 10000000 178 ns/op
Benchmark_StrConcat5-4 20000000 102 ns/op
可见,第5个函数的效率是最高的,虽然它的代码量最多。
其次是第3个函数,其实我们查看第3个函数的源代码就可以发现,它与第5个函数本质上是一样的,但是因为多了对分隔符的拷贝操作,执行时间增加了。我认为这个系统函数可以再优化,判断分隔符是不是空的,如果是空的,就按第5个函数那个处理,这样效率还能提升15%。
附,strings.Join函数源代码:
// Join concatenates the elements of a to create a single string. The separator string
// sep is placed between elements in the resulting string.
func Join(a []string, sep string) string {
switch len(a) {
case 0:
return ""
case 1:
return a[0]
case 2:
// Special case for common small values.
// Remove if golang.org/issue/6714 is fixed
return a[0] + sep + a[1]
case 3:
// Special case for common small values.
// Remove if golang.org/issue/6714 is fixed
return a[0] + sep + a[1] + sep + a[2]
}
n := len(sep) * (len(a) - 1)
for i := 0; i < len(a); i++ {
n += len(a[i])
}
b := make([]byte, n)
bp := copy(b, a[0])
for _, s := range a[1:] {
bp += copy(b[bp:], sep)
bp += copy(b[bp:], s)
}
return string(b)
}