Golang高性能编程笔记--字符串拼接

Golang中引入五种字符串拼接方法,分别如下:

  1.+拼接法

  2.fmt.Sprintf()

  3.strings.Builder

  4.bytes.Buffer

  5.[]byte

代码示例,这里将根据《Go语言高性能编程》中的一节,来看一下这五种具体的方法:

package main

import (
	"bytes"
	"fmt"
	"math/rand"
	"strings"
	"time"
)

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

func GenerateRandomStr(n string) string {
	var l = len(n)
	b := make([]byte, l)
	for i := range b {
		rand.Seed(time.Now().UnixNano())
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}
	return string(b)
}

func PlusConcat(n int, str string) string {
	s := ""
	for i := 0; i < n; i++ {
		s += str
	}
	return s
}
func sprintfConcat(n int, str string) string {
	s := ""
	for i := 0; i < n; i++ {
		s = fmt.Sprintf("%s%s", s, str)
	}
	return s
}
func builderConcat(n int, str string) string {
	var builder strings.Builder
	for i := 0; i < n; i++ {
		builder.WriteString(str)
	}
	return builder.String()
}
func bufferConcat(n int, s string) string {
	buf := new(bytes.Buffer)
	for i := 0; i < n; i++ {
		buf.WriteString(s)
	}
	return buf.String()
}
func byteConcat(n int, str string) string {
	buf := make([]byte, 0)
	for i := 0; i < n; i++ {
		buf = append(buf, str...)
	}
	return string(buf)
}
func main() {
	var str = GenerateRandomStr("abcdefg")
	fmt.Println(str)
	fmt.Println("+拼接", PlusConcat(3, str))
	fmt.Println("fmt.Sprintf:", sprintfConcat(3, str))
	fmt.Println("strings.Builder:", builderConcat(3, str))
	fmt.Println("bytes.Buffer:", bufferConcat(3, str))
	fmt.Println("[]byte:", byteConcat(3, str))

}

官方给的建议是第三种:strings.Builder

golang对于第三种strngs.Builder还提供了预分配内存的模式:

func builderConcat(n int, str string) string {
	var builder strings.Builder
	builder.Grow(n * len(str))
	for i := 0; i < n; i++ {
		builder.WriteString(str)
	}
	return builder.String()
}

性能比较

首先看一下strings.Builder与+的差距大的原因:

字符串在 Go 语言中是不可变类型,占用内存大小是固定的,当使用 + 拼接 2 个字符串时,生成一个新的字符串,那么就需要开辟一段新的空间,新空间的大小是原来两个字符串的大小之和。拼接第三个字符串时,再开辟一段新空间,新空间大小是三个字符串大小之和,以此类推。

strings.Builderbytes.Buffer,包括切片 []byte 的内存是以倍数申请的。例如,初始大小为 0,当第一次写入大小为 10 byte 的字符串时,则会申请大小为 16 byte 的内存(恰好大于 10 byte 的 2 的指数),第二次写入 10 byte 时,内存不够,则申请 32 byte 的内存,第三次写入内存足够,则不申请新的,以此类推。

strings.Builder与bytes.Buffer,[]byte的分析

strings.Builderbytes.Buffer 底层都是 []byte 数组,但 strings.Builder 性能比 bytes.Buffer 略快约 10% 。一个比较重要的区别在于,bytes.Buffer 转化为字符串时重新申请了一块空间,存放生成的字符串变量,而 strings.Builder 直接将底层的 []byte 转换成了字符串类型返回了回来。

posted @ 2023-05-18 23:06  99号的格调  阅读(186)  评论(0编辑  收藏  举报