字符串在内存中是不可变的,放在只读内存段,因此你可以使用str[0]
来访问,但是不能使用str[0]='a'
来修改。
修改字符串实际上是重新放入新的地址,因此拼接字符串可能出现的性能问题就是频繁的内存分配,比如:
1
2
3
4
5
6
|
func s1(ids [] string ) (s string ) { for _, id := range ids { s += id } return } |
在golang中,具有预先分配内存特性的是切片,如果预先就分配好内存,然后再依次将字符串装进去就避免了内存的频繁分配。
再来看看strings
包的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func Join(elems [] string , sep string ) string { switch len (elems) { case 0 : return "" case 1 : return elems[ 0 ] } n := len (sep) * ( len (elems) - 1 ) for i := 0 ; i < len (elems); i++ { n += len (elems[i]) } var b Builder b.Grow(n) b.WriteString(elems[ 0 ]) for _, s := range elems[ 1 :] { b.WriteString(sep) b.WriteString(s) } return b. String () } |
主要就用到strings.Builder
对象,它包含一个切片。
1
2
3
4
|
type Builder struct { addr *Builder // of receiver, to detect copies by value buf [] byte } |
Builder
的Grow
方法就是主动扩容切片的容积。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// grow copies the buffer to a new, larger buffer so that there are at least n // bytes of capacity beyond len(b.buf). func (b *Builder) grow(n int ) { buf := make ([] byte , len (b.buf), 2 * cap (b.buf)+n) copy (buf, b.buf) b.buf = buf } // Grow grows b's capacity, if necessary, to guarantee space for // another n bytes. After Grow(n), at least n bytes can be written to b // without another allocation. If n is negative, Grow panics. func (b *Builder) Grow(n int ) { b.copyCheck() if n < 0 { panic ( "strings.Builder.Grow: negative count" ) } if cap (b.buf)- len (b.buf) < n { b.grow(n) } } |
到此这篇关于GoLang中拼接字符串性能优化方法详解的文章就介绍到这了,更多相关GoLang拼接字符串内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/raoxiaoya/article/details/124629601