SoFunction
Updated on 2025-03-04

Problems and solutions in string assignment in Go language

String stitching method

use+Number

use+The method of splicing strings is to create a new string every time you splice it, and then copy the original string into the new string, which will lead to a large amount of memory allocation and copying operations, with poor performance.

String formatting functionfunction

Pre-allocatedBuffer

func BufferCapResize() {
  var str = "abcd"
  var buf 
  // Preallocate memory  (4 * 10000) // If there is no such line, the capacity will be expanded when the length is not enough  cap := 0
  for i := 0; i < 10000; i++ {
    if () != cap {
      println("cap:", ())
      cap = ()
    }
    (str)
  }
}
  • Pre-allocatedBuilder
  • Pre-allocated[]byte
  • usefunction

andThe bottom layer is a byte array, butWhen converting strings, you need to reapply the memory space, andIt directly puts the bottom layerbytesConvert to a string to return

  • string([:])Directly force
  • ((), len())Zero copy conversion

String memory leak

Point to the same memory space when intercepting characters

How to avoid:

  • Convert substrings into byte slices, converting them intostring
  • After intercepting, splicing a new string in front
  • useReconstruct new strings

Define a long strings := ("a", 1<<20)

Assignment

Printed at the same addressPrinted onenil

The string will not be copied when assigning, but only changes the underlying pointer pointer.

Original stringsEven if it is reassigned to an empty string,s2Still pointing to the original string, so the original address will not be released

func main() {
  ptr := (*)((&s))
  ("s pointer:", ()) // ① 0xc000180000
  Assign()
}

func Assign() {
  s2 := s
  ptr := (*)((&s2))
  ("Assign:", ())  // ② 0xc000180000

  s := ""
	ptr = (*)((&s))
	("s pointer", ()) // ③ nil

	ptr = (*)((&s2))
	("Assign", ())  // ④ 0xc000180000
  _ = s2
}

Assign by reference

Whether it is assigned through reference or value assignment, it ultimately points to the same address

func main() {
  ptr := (*)((&amp;s))
  ("s pointer:", ())  // ① 0xc000180000
  AssignPointer()
}

func AssignPointer() {
  s2 := &amp;s  // Assign values ​​by reference  ptr := (*)((s2))
  ("AssignPointer:", ())  // ② 0xc000180000
  _ = s2
}

String intercept

s2It's interceptedsBefore the string20Sos2andsThe starting address is the same

This solution can easily lead to memory leaks because stringssThere is a lot of room for application.sIt will not be recycled without use, becauses2Pointed tosAddress

func main() {
  ptr := (*)((&s))
  ("s pointer:", ())  // ① 0xc000100000
  StringSlice()
}

func StringSlice() {
  s2 := s[:20]
  ptr := (*)((&s2))
  ("StringSlice:", ()) // ② 0xc000100000
  _ = s2
}

String pass

The string is passed inside the function. Whether it is a pointer or a value, the address of the actual content of the string in memory is the same.

func main() {
  ptr := (*)((&s))
  ("s pointer:", ()) // ① 0x49b7ba
  f1(s)
  f2(&s)
}
func f1(s string) string {
  ptr := (s)
  ("f1:", ptr) // ② 0x49b7ba
  return s
}
func f2(s *string) *string {
  ptr := (*s)
  ("f2:", ptr) // ③ 0x49b7ba
  return s
}

You may find that it is said that the Internet will not copy when passing pointers, and the copy will occur when passing values, but why is the string not copying now, whether it is passing pointers or passing values, no copying occurs when passing strings.

This is because&sThe function parameters are printedsThe address on the stack will be different every time the function call is called

func main() {
  ptr := (*)((&amp;s))
  ("s pointer:", ()) // ① 0x49b7ba
  ("s Address:", &amp;s) // 0x528650
  f1(s)
  f2(&amp;s)
}
func f1(s string) string {
	("f1 s:", &amp;s)    // 0xc000014070
  ptr := (s)
	("f1:", ptr) // 0x49b7ba
	return s
}
func f2(s *string) *string {
	("f2 s:", s)   // 0x528650
  ptr := (*s)
	("f2:", ptr) // 0x49b7ba
	return s
}

How to change the string address

1. Forced

func StringSlice1(s string) string {
  ("string:", (s))  // 0xc000100000
  s1 := string([]byte(s[:20]))
  ptr := (s1)
  ("StringSlice1:", ptr) // 0xc0000bc000
  return s1
}

2. Change the first character and you can change its1Address

func StringSlice2(s string) string {
  ("string:", (s))  // 0xc000100000
  s1 := (" " + s[:20])[1:]
  ptr := (s1)
  ("StringSlice2:", ptr) // 0xc000018199
  return s1
}

3. UseStringsBuilderChanges1Address

func StringSliceUseBuilder(s string) string {
  ("string:", (s)) // 0xc000100000
  var b 
  (20)
  (s[:20])
  s1 := ()
  ptr := (s1)
  ("StringSliceUseBuilder:", ptr) // 0xc0000b0000
  return s1
}

Character switching zero copy conversion

Although both are slice operations,s1will change the address, ands2Will not change the address

  • s1Pointer type that is forced to string
  • s2: Right firstsDo a finger fetch, convert it into a string slice pointer type, and then get the content of the pointer

sos2The method is zero copy conversion

func main() {
  ptr := (*)((&s))
  ("s pointer:", ()) // 0xc000180000
}
func stringToBytes() {
  s1 := []byte(s)
  ("s1: ", (s1)) // 0xc000280000

  s2 := *(*[]byte)((&s))
  ("s2: ", (s2)) // 0xc000180000
}

This is the article about the problems and solutions in string assignment in Go. For more related contents of Go string assignment, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!