浅析Golang中字符串拼接问题

作者:落风雪 时间:2024-04-28 09:17:07 

1.概述

Go的字符串是一个不可改变的数据结构,这和其他语言如JAVA,C++等的设定很类似.总体来说,有如下五种拼接方式,下面我们将论述各种方式的性能问题,以及如何选择.

浅析Golang中字符串拼接问题

(golang字符串,内存模型)

type StringHeader struct {
Data uintptr
Len  int
}

注意:字符串具有不可改变的特性,即便通过指针等变相操作

var a string = "old"
bptr := (*reflect.StringHeader)(unsafe.Pointer(&a))
dataPtr := (*byte)(unsafe.Pointer(bptr.Data))
var b = [3]byte{'n', 'e', 'w'}
*dataPtr = b[0] //报错
fmt.Println(bptr)

2.Golang中字符串拼接的方式

方式一、直接+

当使用连接符 + 拼接两个字符串时,会生成一个新的字符串并开辟新的内存空间,空间大小等于两个字符串之和。在训中中时,不断拼接新的字符串,这样就会不断申请内存空间, 性能就会越来越差。 所以,在字符串密集拼接场景中,使用 + 会严重降低性能。包括热路径的代码.

方式二、strings.Builder

func Benchmark_StringsBuilder(b *testing.B) {
var sb strings.Builder
for i := 0; i < b.N; i++ {
sb.WriteString("hello world")
}
_ = sb.String()
}

方式三、bytes.Buffer

func Benchmark_BytesBuffer(b *testing.B) {
var buf bytes.Buffer
for i := 0; i < b.N; i++ {
buf.WriteString("hello world")
}
_ = buf.String()
}

方式四、fmt.Fprint(&buf,&str)

方式五、strings.Join

性能不是最优,但在切片的情况下,可以用来拼接

3.总结

Benchmark_StringAdd Benchmark_StringAdd-8 117806 127059 ns/op Benchmark_BytesBuffer Benchmark_BytesBuffer-8 38938282 25.88 ns/op Benchmark_StringsBuilder Benchmark_StringsBuilder-8 57249450 18.53 ns/op

3.1 性能方面,strings.Builder 比 bytes.Buffer 快差不多 20%,

原因:strings.Builder 和 bytes.Buffer 底层都是一个 []byte,但是 bytes.Buffer 转换字符串时会重新申请内存空间用来存放, 而 strings.Builder 直接将底层的 []byte 利用指针的方式强转为字符串.

//strings.Builder的String()
func (b *Builder) String() string {
   return *(*string)(unsafe.Pointer(&b.buf))
}

//bytes.Builder的String()
func (b *Buffer) String() string {
   if b == nil {
       // Special case, useful in debugging.
       return "<nil>"
   }
   return string(b.buf[b.off:])
}

3.2 strings.Builder通常性能最优,但底层依赖于[]byte,所以如果平凡扩容就不妙了,因此我们需要借助它的Grow方法,以已分配最终[]byte的容量,避免因为扩容带来的性能损失

func Benchmark_StringConcat(b *testing.B) {
   str := "hello world"
   var sb strings.Builder
   sb.Grow(b.N * len(str))
   for i := 0; i < b.N; i++ {
       sb.WriteString(str)
   }
   _ = sb.String()
}

3.3 strings.Builder没有拷贝构造(借用C++说法),因为

type Builder struct {  
addr *Builder // of receiver, to detect copies by value  
buf []byte  //如果拷贝,这个buf共享,最后导致数据混乱
}

来源:https://juejin.cn/post/7199903805509124151

标签:Go,字符串,拼接
0
投稿

猜你喜欢

  • asp函数InstrRev()介绍及获取文件名例子

    2007-11-19 19:01:00
  • 浅谈MySQL安装starting the server失败的解决办法

    2024-01-25 06:37:22
  • MySQL 按指定字段自定义列表排序的实现

    2024-01-16 08:09:22
  • Vue express鉴权零基础入门

    2024-05-13 09:11:29
  • 解决pycharm运行程序出现卡住scanning files to index索引的问题

    2023-02-14 05:43:52
  • Pycharm安装并配置jupyter notebook的实现

    2022-11-14 14:24:28
  • Python subprocess库的使用详解

    2021-10-25 04:59:32
  • 实例介绍Python中整型

    2021-03-09 08:00:33
  • opencv+python实现均值滤波

    2023-10-21 15:00:58
  • python reduce 函数使用详解

    2022-11-01 22:20:57
  • windows下python安装pip方法详解

    2023-12-13 19:43:16
  • 关于Python函数的定义和参数

    2021-05-08 20:37:28
  • 该用多大的字

    2009-05-17 14:39:00
  • Dreamweaver4探谜系列(1)

    2010-09-05 21:12:00
  • PHP _construct()函数讲解

    2023-06-14 16:56:43
  • MySQL query_cache_type 参数与使用详解

    2024-01-29 08:02:58
  • Python Vaex实现快速分析100G大数据量

    2021-05-24 08:48:58
  • JavaScript中的匀速运动和变速(缓冲)运动详细介绍

    2024-06-07 15:28:03
  • Python实现新浪博客备份的方法

    2021-12-26 18:22:01
  • 使用Pycharm(Python工具)新建项目及创建Python文件的教程

    2022-06-07 11:43:52
  • asp之家 网络编程 m.aspxhome.com