当前位置: 首页 > 面试题库 >

如何在Go中有效地串联字符串

诸经略
2023-03-14
问题内容

在Go中,a string是原始类型,这意味着它是只读的,对其的每次操作都会创建一个新的字符串。

因此,如果我想多次连接字符串而又不知道结果字符串的长度,那么最好的方法是什么?

天真的方法是:

s := ""
for i := 0; i < 1000; i++ {
    s += getShortStringFromSomewhere()
}
return s

但这似乎不是很有效。


问题答案:

新方法:

在Go 1.10+中strings.Builder,这里是。

生成器用于使用Write方法有效地构建字符串。它最大程度地减少了内存复制。零值可以使用了。

与几乎相同bytes.Buffer。

package main

import (
    "strings"
    "fmt"
)

func main() {
    // ZERO-VALUE:
    //
    // It's ready to use from the get-go.
    // You don't need to initialize it.
    var str strings.Builder

    for i := 0; i < 1000; i++ {
        str.WriteString("a")
    }

    fmt.Println(str.String())
}

注意

  • 不要复制StringBuilder值,因为它会缓存基础数据。
  • 如果要共享StringBuilder值,请使用指向它的指针。

支持的接口

正在考虑现有接口的情况下实现StringBuilder的方法。这样您就可以在代码中轻松切换到新的Builder类型。

  • Grow(int)-> bytes.Buffer#Grow
  • Len()int- > bytes.Buffer#Len
  • Reset()-> bytes.Buffer#Reset
  • String()字符串-> fmt.Stringer
  • Write([] byte)(int,error)-> io.Writer
  • WriteByte(byte)错误-> io.ByteWriter
  • WriteRune(rune)(int,error)-> bufio.Writer#WriteRune - bytes.Buffer#WriteRune
  • WriteString(string)(int,error)-> io.stringWriter

与bytes.Buffer的差异

  • 它只能增长或重置。

  • 它具有内置的copyCheck机制,可防止意外复制它:

  • func (b *Builder) copyCheck() { … }

  • 在中bytes.Buffer,人们可以像这样访问基础字节:(*Buffer).Bytes()。

  • strings.Builder 可以防止此问题。

  • 有时,这不是问题,而是需要的。
  • 例如:对于将字节传递给io.Readeretc 时的偷窥行为。

旧方法:

使用bytes包装。它具有Buffer实现的类型io.Writer

package main

import (
    "bytes"
    "fmt"
)

func main() {
    var buffer bytes.Buffer

    for i := 0; i < 1000; i++ {
        buffer.WriteString("a")
    }

    fmt.Println(buffer.String())
}

这是在O(n)时间内完成的。



 类似资料:
  • 问题内容: 我写了一个Java程序,其中需要附加一个字符串 到现有的。 因此,字符串逐渐变长。我发现每次附加所花费的时间也越来越长。有什么办法可以改善这一点? 我想到的实现包括: 要么 他们表现相似。我认为导致这些不良性能的主要原因是特殊类型。它为每个作业创建一个新对象。如果您也这样认为,这是否意味着我最好使用其他类型,例如字节数组? 问题答案: 使用类。您尝试执行的操作效率更高。

  • 问题内容: 我知道使用“ +”串联运算符来构建字符串效率很低,这就是为什么建议使用StringBuilder类的原因,但是我想知道这种模式是否也效率低下? 我猜这里编译器会优化分配,好吗? 问题答案: 该特定示例将由编译器内联: Java 9+将使用带有makeConcatWithConstants的invokedynamic来内联此代码,以使其高效。根据输出: 但是,如果 and 是编译时间常数

  • 问题内容: 我想知道如何在Java中连接4个字符串数组。 已经有一个问题了。 如何在Java中连接两个数组? 但是我试图复制它,但是它对我不起作用。 这是我的代码如下所示: 调用方法: 方法本身: 问题答案: 抛开诸如检查数组是否为的事情null,您可以为其创建通用方法,并在您的特定情况下使用它,如下所示:

  • 问题内容: 在将根据循环被重复。如何将结果另存为新字符串。例如,如果工作“ hello”重复了两次,我现在将如何创建“ hellohello”作为一个全新的字符串。 问题答案:

  • 问题内容: 我有一个在某些情况下会返回字符串的函数,即当程序在Linux或MacOS上运行时,否则返回值应为nil,以便在代码中进一步省略一些特定于OS的检查。 但是,当我尝试编译此代码时,出现错误: test.go:10:3​​:不能在返回参数中使用nil作为类型字符串。 如果我只返回一个空字符串(如),则无法将此返回值与代码中的进一步内容进行比较。 那么问题是如何返回正确的nil字符串值? 谢

  • 问题内容: 给我一个字符串,如果有一个或多个无效字符,则必须返回False,否则返回True。需要注意的是,我只能内置函数和str操作(例如:in,+,indexing,len)和递归。到目前为止,我没有用: 显然,由于递归,该代码无法正常工作,并且在下一次递归迭代之后才将变量加1 。 问题答案: 对于小尺寸(约一千个字符)的DNA序列,这是一个实际的实现 注意事项 在python中使用递归要小心