golang中拼接字符串性能问题

字符串在内存中是不可变的,修改后的字符串会重新放入新的地址,因此拼接字符串可能出现的性能问题就是频繁的内存分配,比如:

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)
	}
}

猜你喜欢

转载自blog.csdn.net/raoxiaoya/article/details/124629601