Go中高效组装字符串,实现类似Java中StringBuilder的功能

Go中可以使用“+”合并字符串,但是这种合并方式效率非常低,每合并一次,就必须遍历一次字符串。Java中提供StringBuilder类来解决这个问题。Go中也有类似的机制,那就是Buffer。以下是示例代码:

package main

import (
    \"bytes\"
    \"fmt\"
)

func main() {
    var buffer bytes.Buffer

    for i := 0; i < 1000; i++ {
        buffer.WriteString(\"a\")
    }

    fmt.Println(buffer.String())
}

使用bytes.Buffer来组装字符串,不需要遍历,只需要将添加的字符串放在缓存末尾即可。

那么这种效率差别有多大呢?我们做个测试,组装10万个“a”。

package main

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

func main() {

    _, t := testBuf()

    //fmt.Println(s)
    fmt.Println(\"string buffer : \", t, \"ns\")

    _, t = testPlus()

    //fmt.Println(ss)
    fmt.Println(\"string plus : \", t, \"ns\")
}

func testPlus() (s string, t int64) {
    start := time.Now().UnixNano()
    for i := 0; i < 100000; i++ {
        s += \"a\"
    }
    end := time.Now().UnixNano()

    return s, end - start
}

func testBuf() (s string, t int64) {
    var buf bytes.Buffer
    start := time.Now().UnixNano()
    for i := 0; i < 100000; i++ {
        buf.WriteString(\"a\")
    }
    s = buf.String()
    end := time.Now().UnixNano()

    return s, end - start
}

测试结果:

string buffer :  3001700 ns
string plus :  1414015200 ns

使用Buffer仅仅用了3ms,而加号则使用了1.4s,差距巨大。而且使用Buffer时,三分之二的时间用在了buf.String()上,也就是说,组装时间仅仅有1ms,其余2ms花在了转换为字符串上。

我本来是组装1万个“a”的,结果使用Buffer的方式测不出时间(时间为0ns),不得已采用的10万,这也说明Buffer效率非常高。

2 评论

  1. 大侠,我遇到个问题,就是如果我想在字符串中插入一个字符串。
    在c#中,使用 stringbuilder 里的 insert就可以了。
    但是golang中,我找了好久,没有什么好的方案,
    可否给个简单的例子,谢谢

  2. 这两种方式适用于不同的场合:标准的“+”操作符适用于两三个字符串的拼接,而bytes.Buffer更适合于大批量的字符串拼接。
    这里有人做了一个测试:http://my.oschina.net/janpoem/blog/406514

发表评论

电子邮件地址不会被公开。