golang字符串拼接方式

     字符串拼接是字符的常见操作。在golang中,遇见了字符串拼接。作为一个长期的C程序员,我第一反应是:字符串拼接函数strcat,但发现golang并无字符串拼接函数。

      我想起了最简单的方法,通过+操作符进行字符串拼接。

      但我查了相关资料后发现:golang中的string类型也是只读且不可变的;因此,这种拼接字符串的方式会导致大量的string创建、销毁和内存分配。如果你拼接的字符串比较多的话,这显然不是一个正确的姿势。

       然后,查找一些可行的方法。

       (1)fmt.Sprintf():该方法内部使用 []byte 实现,不像直接运算符这种会产生很多临时的字符串,但是内部的逻辑比较复杂,有很多额外的判断,还用到了 interface,所以性能也不是很好。

       (2)strings.Join():join会先根据字符串数组的内容,计算出一个拼接之后的长度,然后申请对应大小的内存,一个一个字符串填入,在已有一个数组的情况下,这种效率会很高,但是本来没有,去构造这个数据的代价也不小

       (3)buffer.WriteString():可以当成可变字符使用,对内存的增长也有优化,如果能预估字符串的长度,还可以用 buffer.Grow() 接口来设置 capacity

       (4)strings.Builder:golang拼接倡导的方法。

       倡导尽量用strings.Builder方法,示例如下;     

        var build strings.Builder
        build.WriteString("http://www.your_dsp.com/win?sid=")
        build.WriteString(dsp.RequestId)
        build.WriteString("&impid=")
        build.WriteString(dsp.ImpInfo.Impid)
        build.WriteString("&price={")
        build.WriteString(fmt.Sprintf("%d", rsp.Bid.Price))
        build.WriteString("}")
        fmt.Println(build.String())

 

测试:

我自己写了个程序测试,发现:测试次数越大,fmt.Sprintf 的时间差距与strings.Builder的差距越大,代码如下:

func main(){
   _, miniute, _ := time.Now().Clock()
   var dsp DspInfo = DspInfo{
      "91b5e18c-014c-1000-e71a-3e9942b60043",
      "91b5e18c-014c-1000-e71a-3e9942b60043",
      time.Now().Format("2006010215"),
      int32(miniute),
      "5d0861a92e5f930fe8a66025"}

   i := 0
   t1 := time.Now().UnixNano()
   for i < 10000000 {
      //combineURL("win" , &dsp, 100)
      var build strings.Builder
      build.WriteString("http://www.dsp.com")
      build.WriteString("/")
      //build.WriteString("http://www.dsp.com/")
      build.WriteString("win")
      build.WriteString("?sid=")
      build.WriteString(dsp.RequestId)
      build.WriteString("&impid=")
      build.WriteString(dsp.ImpId)
      //build.WriteString("&price={PRICE}&extdata=")
      build.WriteString("&price={PRICE}")
      build.WriteString("&extdata=")
      build.WriteString(dsp.TimeHour)
      build.WriteString(strconv.FormatInt(int64(dsp.Miniute), 10))
      build.WriteString("_")
      build.WriteString(dsp.MmId)

      build.String()

      i++
   }
   t2 := time.Now().UnixNano()

   i = 0
   t3 := time.Now().UnixNano()
   for i < 10000000 {
      fmt.Sprintf("http://www.dsp.com/%s?sid=%s&impid=%s&price={PRICE}&extdata=%s%d_%s",
         "win", dsp.RequestId, dsp.ImpId, dsp.TimeHour, dsp.Miniute,dsp.MmId)
      i++
   }
   t4 := time.Now().UnixNano()

   i = 0
   t5 := time.Now().UnixNano()

   for i < 10000000 {
      var buff bytes.Buffer
      // 向buff中写入字符/字符串
      buff.Write([]byte("http://www.dsp.com/"))
      buff.WriteString("win")
      buff.WriteString("?sid=")
      buff.WriteString(dsp.RequestId)
      buff.WriteString("&impid=")
      buff.WriteString(dsp.ImpId)
      buff.WriteString("&price={PRICE}")
      buff.WriteString("&extdata=")
      buff.WriteString(dsp.TimeHour)
      buff.WriteString(strconv.FormatInt(int64(dsp.Miniute), 10))
      buff.WriteString("_")
      buff.WriteString(dsp.MmId)

      buff.String()
      i++
   }
   t6 := time.Now().UnixNano()

   fmt.Println(t1, "\n", t2, "\n", t3, "\n", t4, "\n", t5, "\n", t6)
   fmt.Println("delta T1: ", t2 - t1, "\ndelta T2:", t4 - t3, "\ndelta T3:", t6 - t5)

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值