penglongli / blog

18 stars 1 forks source link

go 的字符串拼接 #43

Open penglongli opened 6 years ago

penglongli commented 6 years ago

参考:

字符串操作

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

for i := 0; i < 100000; i++ { result += str }

- fmt.Sprintf
```go
var result string
str := "ABCD "

for i := 0; i < 100000; i++ {
    result = fmt.Sprintf("%s%s", result, str)
}

for i := 0; i < 100000; i++ { buffer.WriteString(str) } result = buffer.String()

- copy
```go
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 即可满足需求。