如何在没有加号操作的情况下在GoLang中添加字符串?

Vie*_*iet 3 string stringbuilder go

这可能是重复的,但我无法在任何地方找到正确的答案。如何在不使用+运算符的情况下在 GoLang 中添加字符串(这被认为很慢)?

我知道我可以使用但只能附加来附加到字符串。如果我想前置,我必须在前缀中写入后缀字符串,如下所示:bytes.BufferWriteString

package main

import (
    "bytes"
    "fmt"
)

func main() {
    var b bytes.Buffer 
      
    b.WriteString("W") 
    b.WriteString("o") 
    b.WriteString("r") 
    b.WriteString("l") 
    b.WriteString("d") 
   
    var a bytes.Buffer
    a.WriteString("Hello ")
    a.WriteString(b.String())
  
    fmt.Println(a.String()) 
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的办法?

was*_*mup 6

如果它位于性能关键路径上,则使用它strings.Builder是可行的方法,否则简单就更好了;如果您事先知道长度,您也可以使用数组或切片并进行复制(感谢@mh-cbon,并参见slice-allocation-performance): +

go test -benchtime=4731808x -benchmem -bench .
BenchmarkBufferArraySimplified-8  4731808   11.36 ns/op   0 B/op  0 allocs/op
BenchmarkBufferArray-8            4731808   62.19 ns/op   0 B/op  0 allocs/op
BenchmarkBuilder-8                4731808  140.7 ns/op   32 B/op  3 allocs/op
BenchmarkBuffer-8                 4731808  200.7 ns/op  128 B/op  2 allocs/op
BenchmarkByteAppend-8             4731808  223.2 ns/op   16 B/op  4 allocs/op
BenchmarkPlus-8                   4731808  226.2 ns/op   16 B/op  4 allocs/op
BenchmarkByteCopy-8               4731808  254.1 ns/op   32 B/op  5 allocs/op
BenchmarkPrepend-8                4731808  273.7 ns/op   24 B/op  5 allocs/op
Run Code Online (Sandbox Code Playgroud)

基准:

package main

import (
    "bytes"
    "strings"
    "testing"
)

func BenchmarkBufferArraySimplified(b *testing.B) {
    for i := 0; i < b.N; i++ {
        var y [11]byte // should you know the length beforehand
        y[6] = 'W'
        y[7] = 'o'
        y[8] = 'r'
        y[9] = 'l'
        y[10] = 'd'

        copy(y[0:], "Hello ")
        _ = string(y[:])
    }
}
func BenchmarkBufferArray(b *testing.B) {
    for i := 0; i < b.N; i++ {
        var y [11]byte
        hello := "Hello "
        n := len(hello) // should you know the length beforehand
        b := bytes.NewBuffer(y[:n])
        b.WriteString("W")
        b.WriteString("o")
        b.WriteString("r")
        b.WriteString("l")
        b.WriteString("d")

        a := bytes.NewBuffer(y[:0])
        a.WriteString(hello) // prepend
        _ = b.String()
    }
}
func BenchmarkBuilder(b *testing.B) {
    for i := 0; i < b.N; i++ {
        var b strings.Builder
        b.WriteString("W")
        b.WriteString("o")
        b.WriteString("r")
        b.WriteString("l")
        b.WriteString("d")

        var a strings.Builder
        a.WriteString("Hello ") // prepend
        a.WriteString(b.String())
        _ = a.String()
    }
}
func BenchmarkBuffer(b *testing.B) {
    for i := 0; i < b.N; i++ {
        var b bytes.Buffer
        b.WriteString("W")
        b.WriteString("o")
        b.WriteString("r")
        b.WriteString("l")
        b.WriteString("d")

        var a bytes.Buffer
        a.WriteString("Hello ") // prepend
        a.WriteString(b.String())
        _ = a.String()
    }
}
func BenchmarkByteAppend(b *testing.B) {
    for i := 0; i < b.N; i++ {
        b := "W"
        b += "o"
        b += "r"
        b += "l"
        b += "d"

        _ = ByteAppend("Hello ", b) // prepend
    }
}
func ByteAppend(a, b string) string {
    return string(append([]byte(a), []byte(b)...)) // a+b
}
func BenchmarkPlus(b *testing.B) {
    for i := 0; i < b.N; i++ {
        b := "W"
        b += "o"
        b += "r"
        b += "l"
        b += "d"

        _ = "Hello " + b // prepend
    }
}
func BenchmarkByteCopy(b *testing.B) {
    for i := 0; i < b.N; i++ {
        b := "W"
        b += "o"
        b += "r"
        b += "l"
        b += "d"

        _ = byteCopy("Hello ", b) // prepend
    }
}
func byteCopy(a, b string) string {
    c := make([]byte, len(a)+len(b))
    copy(c, a)
    copy(c[len(a):], b) // a+b
    return string(c)
}
func BenchmarkPrepend(b *testing.B) {
    for i := 0; i < b.N; i++ {
        b := " "
        b += "W"
        b += "o"
        b += "r"
        b += "l"
        b += "d"

        _ = string(prepend([]byte(b), []byte("Hello"))) // prepend
    }
}

// prepend: insert b into a at index 0:  len(a) >= len(b)
func prepend(a, b []byte) []byte {
    // if len(a) >= len(b) {
    a = append(a[:len(b)], a...) // grow
    copy(a, b)
    return a
    // }
    // return append(b, a...)
}
Run Code Online (Sandbox Code Playgroud)

  • 很高兴知道更快的替代方案,但这并不能回答问题。OP 要求一种将 **_prepend_** 字符串添加到现有字符串的方法。 (2认同)