GoLang中拼接字符串性能优化方法详解

字符串在内存中是不可变的,放在只读内存段,因此你可以使用str[0]来访问,但是不能使用str[0]='a'来修改。

修改字符串实际上是重新放入新的地址,因此拼接字符串可能出现的性能问题就是频繁的内存分配,比如:

func s1(ids []string) (s string) {
	for _, id := range ids {
	s += id
	}
	return
}

在golang中,具有预先分配内存特性的是切片,如果预先就分配好内存,然后再依次将字符串装进去就避免了内存的频繁分配。

再来看看strings包的实现

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对象,它包含一个切片。

type Builder struct {
	addr *Builder // of receiver, to detect copies by value
	buf []byte
}

BuilderGrow方法就是主动扩容切片的容积。

// 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)
	}
}
作者:raoxiaoya原文地址:https://blog.csdn.net/raoxiaoya/article/details/124629601

%s 个评论

要回复文章请先登录注册