SoFunction
Updated on 2025-03-01

Details of string splicing methods in Go language

1. string type

stringA value of a type can be split into a sequence containing multiple characters (rune type) or into a sequence containing multiple bytes (byte type). One of themruneThe type value represents aUnicode Character, oneruneThe type value occupies four bytes, and the bottom layer is a UTF-8 encoded value, which is actually an alias type of the int32 type.

package main

import (
 "fmt"
)

func main() {
 str := "Hello world"
 ("The string: %q\n", str)
 ("runes(char): %q\n", []rune(str))
 ("runes(hex): %x\n", []rune(str))
 ("bytes(hex): [% x]\n", []byte(str))
}

Execution results:

The string: "Hello world"
runes(char): ['You' 'ok' 'w' 'o' 'o' 'r' 'l' 'd']
runes(hex): [4f60 597d 77 6f 72 6c 64]
bytes(hex): e4 bd a0 e5 a5 bd 77 6f 72 6c 64

As you can see, English characters use one byte, while Chinese characters need three bytes. Use below for range The statement traverses the above string:

for index, value := range str {
    ("%d: %q [% x]\n", index, value, []byte(string(value)))
}

The execution results are as follows:

0: 'You' [e4 bd a0]
3: 'OK' [e5 a5 bd]
6: 'w' [77]
7: 'o' [6f]
8: 'r' [72]
9: 'l' [6c]
10: 'd' [64]

indexThe index value is not 0-6, adjacentUnicode The index value of a character is not necessarily continuous, because Chinese characters take up 3 bytes and have a width of 3.

2. strings package

2.1 Type

The advantages are mainly reflected in string splicing, which is more efficient than using + splicing.

  • The existing value cannot be changed and can only be reset (Reset()Method) or splice more content.
  • Once calledBuilderValues ​​cannot be copied in any way, such as passing values ​​between functions, passing values ​​through channels, assigning values ​​to variables, etc.
  • When splicing,BuilderThe value will automatically expand its content container, and can also be usedGrowMethod to manually expand capacity.
package main

import (
 "fmt"
 "strings"
)
func main() {
 var builder1 
 ("hello")
 (' ')
 ("world")
 ([]byte{' ', '!'})

 (()) 

 f1 := func(b ) {
  // ("world !") // An error will be reported }
 f1(builder1)

 ()
 ("The length 0f builder1: %d\n", ())

}

Execution results:

hello world !
The length 0f builder1: 0

2.2 Type

Types can be used to read strings efficiently, and it enables efficient reading by using the read count mechanism, which saves the number of bytes read and also represents the starting index position of the next read.

package main

import (
 "fmt"
 "strings"
)
func main() { 
 reader1 := ("hello world!")
 buf1 := make([]byte, 6)
    ("reading index: %d\n", ()-int64(()))
 
    (buf1)
 (string(buf1))
    ("reading index: %d\n", ()-int64(()))
    
 (buf1)
 (string(buf1))
    ("reading index: %d\n", ()-int64(()))
}

Execution results:

reading index: 0
hello
reading index: 6
world!
reading index: 12

You can see that after each read, the read count will increase.

stringsPackedReadAtThe method does not read based on the read count, nor does it update the read count. It can be read freely based on the offsetReaderContent in the value.

package main

import (
 "fmt"
 "strings"
)
func main() {
    reader1 := ("hello world!")
    buf1 := make([]byte, 6)
 offset1 := int64(6)
 n, _ := (buf1, offset1) 
 (string(buf2))
}

Execution results:

world!

Can also be usedSeekMethod to specify the starting index position for the next read.

package main

import (
 "fmt"
 "strings"
    "io"
)
func main() {
    reader1 := ("hello world!")
    buf1 := make([]byte, 6)
 offset1 := int64(6)
 readingIndex, _ := (offset1, )
 ("reading index: %d\n", readingIndex)

 (buf1)
 ("reading index: %d\n", ()-int64(()))
 (string(buf1))
}

Execution results:

reading index: 6
reading index: 12
world!

3、

bytesPackage andstringsSimilar to the package,stringsThe package is mainly aimed atUnicode characters and UTF-8 encoded strings, andbytesThe package mainly faces byte and byte slices, which are mainly used as buffers for byte sequences.Read counts are used for reading and writing data.

It has read and write functions, and the following are their simple usage methods.

3.1: Write data

andSame,Can be used to splice strings,The content container will also be automatically expanded.Please see the following code:

package main

import (
 "bytes"
 "fmt"
)

func DemoBytes() {
 var buffer 
 ("hello ")
 ("world !")
 (())
}

Execution results:

hello world !

3.2: Read data

Read data also uses read counts. It should be noted that after performing the read operation,LenThe method returns the length of the unread content.Let's take a look at the code directly:

package main

import (
 "bytes"
 "fmt"
)

func DemoBytes() {
 var buffer 
 ("hello ")
 ("world !")
    
    p1 := make([]byte, 5)
 n, _ := (p1)
    
 (string(p1))
 (())
    ("The length of buffer: %d\n", ())
}

Execution results:

hello
 world !
The length of buffer: 8

4. String stitching

After a brief understanding of the string type, strings package and types, let’s introduce the string splicing method in golang.

/p/349672248

go test -bench=. -run=^BenchmarkDemoBytes$

4.1 Direct addition

The easiest way is to add directly. Since the value of the string type is immutable, a new string will be generated when string splicing is performed, and the spliced ​​strings will be copied into a new continuous memory space in turn. If there are a large number of string splicing operations, using this method is very memory-consuming.

package main

import (
 "bytes"
 "fmt"
 "time"
)

func main() {
 str1 := "hello "
 str2 := "world !"
    str3 := str1 + str2
    (str3) 
}

4.

It was introduced earlierCan be used to splice strings:

var builder1 
("hello ")
("world !")

4.3 ()

Can also be usedMethod, actuallyJoin()Called WriteStringmethod;

str1 := "hello "
str2 := "world !"
str3 := ""

str3 = ([]string{str3,str1},"")
str3 = ([]string{str3,str2},"")

4.4

Can also be used for splicing:

var buffer 

("hello ")
("world !")

4.5 append method

Can also be usedGoBuilt-in functionsappendMethod, used to splice slices:

package main

import (
 "fmt"
)

func DemoAppend(n int) {
 str1 := "hello "
 str2 := "world !"
 var str3 []byte

    str3 = append(str3, []byte(str1)...)
    str3 = append(str3, []byte(str2)...)
 (string(str3))
}

Execution results:

hello world !

4.6

fmtIn the packageSprintfMethods can also be used to splice strings:

str1 := "hello "
str2 := "world !"
str3 := ("%s%s", str1, str2)

5. String stitching performance test

Let’s test the performance of these 6 methods and write test source code articlesstrcat_test.go

package benchmark

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

func DemoBytesBuffer(n int) {
 var buffer 

 for i := 0; i < n; i++ {
  ("hello ")
  ("world !")
 }
}

func DemoWriteString(n int) {
 var builder1 
 for i := 0; i < n; i++ {
  ("hello ")
  ("world !")
 }
}

func DemoStringsJoin(n int) {
 str1 := "hello "
 str2 := "world !"
 str3 := ""
 for i := 0; i < n; i++ {
  str3 = ([]string{str3, str1}, "")
  str3 = ([]string{str3, str2}, "")
 }

}

func DemoPlus(n int) {

 str1 := "hello "
 str2 := "world !"
 str3 := ""
 for i := 0; i < n; i++ {
  str3 += str1
  str3 += str2
 }
}

func DemoAppend(n int) {

 str1 := "hello "
 str2 := "world !"
 var str3 []byte
 for i := 0; i < n; i++ {
  str3 = append(str3, []byte(str1)...)
  str3 = append(str3, []byte(str2)...)
 }
}

func DemoSprintf(n int) {
 str1 := "hello "
 str2 := "world !"
 str3 := ""
 for i := 0; i < n; i++ {
  str3 = ("%s%s", str3, str1)
  str3 = ("%s%s", str3, str2)
 }
}

func BenchmarkBytesBuffer(b *) {
 for i := 0; i < ; i++ {
  DemoBytesBuffer(10000)
 }
}

func BenchmarkWriteString(b *) {
 for i := 0; i < ; i++ {
  DemoWriteString(10000)
 }
}

func BenchmarkStringsJoin(b *) {
 for i := 0; i < ; i++ {
  DemoStringsJoin(10000)
 }
}

func BenchmarkAppend(b *) {
 for i := 0; i < ; i++ {
  DemoAppend(10000)
 }
}

func BenchmarkPlus(b *) {
 for i := 0; i < ; i++ {
  DemoPlus(10000)
 }
}

func BenchmarkSprintf(b *) {
 for i := 0; i < ; i++ {
  DemoSprintf(10000)
 }
}


Perform performance tests:

$ go test -bench=. -run=^$
goos: windows
goarch: amd64
pkg: testGo/benchmark
cpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
BenchmarkBytesBuffer-8              3436            326846 ns/op
BenchmarkWriteString-8              4148            271453 ns/op
BenchmarkStringsJoin-8                 3         402266267 ns/op
BenchmarkAppend-8                   1923            618489 ns/op
BenchmarkPlus-8                        3         345087467 ns/op
BenchmarkSprintf-8                     2         628330850 ns/op
PASS
ok      testGo/benchmark        9.279s

By the average time, you can seeWriteStringThe method is most efficient in execution.SprintfThe method is minimally efficient.

  • We seeThe method is also relatively low in efficiency. In the above scenario, it is relatively low in efficiency. It is very efficient in merging existing string arrays.
  • If you want to splice a large number of strings continuously, it is recommended to useWriteStringMethod, if it is a small number of string splicing, you can also use + directly.
  • appendThe method is also very efficient, and it is mainly used for slicing slices.
  • Although the method is inefficient, in a small amount of data stitching, if you want to splice other data types, you can use it to solve it perfectly:
name := "zhangsan"
age := 20
str4 := ("%s is %d years old", name, age)
(str4)  // zhangsan is 20 years old

This is the end of this article about the detailed string splicing method in Go. For more relevant string splicing method content in Go, please search for my previous article or continue browsing the related articles below. I hope you will support me in the future!