blog icon indicating copy to clipboard operation
blog copied to clipboard

go 的字符串拼接

Open penglongli opened this issue 7 years ago • 0 comments
trafficstars

参考:

  • https://gocn.io/question/265
  • https://stackoverflow.com/questions/1760757/how-to-efficiently-concatenate-strings-in-go/23857998#23857998

字符串操作

go 的字符串操作有如下的方式,我们用累加 ABCD 1000 次举例

  • + 操作符
var result string
str := "ABCD "

for i := 0; i < 100000; i++ {
	result += str
}
  • fmt.Sprintf
var result string
str := "ABCD "

for i := 0; i < 100000; i++ {
	result = fmt.Sprintf("%s%s", result, str)
}
  • bytes.Buffer
var result string
var buffer bytes.Buffer
str := "ABCD "

for i := 0; i < 100000; i++ {
	buffer.WriteString(str)
}
result = buffer.String()
  • copy
NUM := 100000
str := "ABCD "

bs := make([]byte, len(str) * NUM)
bl := 0

for n := 0; n < NUM; n++ {
	bl += copy(bs[bl:], str)
}

fmt.Println(len(string(bs)))

如果有多个字符串,直接使用 bytes.Buffer 是最简单且快速的。最快的仍然是 copy,下边是测试。

压力测试

我们暂时不用 go 自带的测试用例方法,直接用 Timer 来做。

package main

import (
	"bytes"
	"fmt"
	"time"
)

var (
	NUM = 100000
	STR = "ABCD "

	operate = map[string]func(){
		"add":    stringAdd,
		"printf": stringPrintf,
		"buffer": stringBuffer,
		"copy":   stringCopy,
	}
)

func main() {
	for _, f := range operate {
		f()
	}
}

func stringAdd() {
	var result string

	start := time.Now()
	for i := 0; i < 100000; i++ {
		result += STR
	}
	duration := time.Since(start)

	fmt.Printf("'+': %s\n", duration)
}

func stringPrintf() {
	var result string

	start := time.Now()
	for i := 0; i < 100000; i++ {
		result = fmt.Sprintf("%s%s", result, STR)
	}
	duration := time.Since(start)

	fmt.Printf("'fmt.Printf': %s\n", duration)
}

func stringBuffer() {
	var buffer bytes.Buffer

	start := time.Now()
	for i := 0; i < 100000; i++ {
		buffer.WriteString(STR)
	}
	buffer.String()

	duration := time.Since(start)

	fmt.Printf("'bytes.Buffer': %s\n", duration)
}

func stringCopy() {
	bs := make([]byte, len(STR)*NUM)
	bl := 0

	start := time.Now()
	for n := 0; n < NUM; n++ {
		bl += copy(bs[bl:], STR)
	}
	_ = string(bs)

	duration := time.Since(start)
	fmt.Printf("'copy': %s\n", duration)
}

直接上结果:

'+': 6.764858478s
'fmt.Printf': 7.903179057s
'bytes.Buffer': 1.247555ms
'copy': 487.435µs

可以看出来,copy 是最快的,Buffer 其次。一般来说用 Buffer 即可满足需求。

penglongli avatar Dec 07 '17 13:12 penglongli