SoFunction
Updated on 2025-03-03

Detailed explanation of golang slice memory application skills

In Go, slices are a very frequently used aggregate type. They represent variable-length sequences and the underlying references an array object. A slice consists of three parts: pointer, length and capacity. The pointer points to the memory address of the underlying array element corresponding to the first element of the slice itself.

The type declaration of slices is as follows:

type slice struct {
 array 
 len  int
 cap  int
}

The data of the underlying array can be shared between multiple slices, and the referenced array intervals may overlap. Using this feature of slices, we can invert, filter and deduplicate slices in the original memory space, so that there is no need to declare a slice pointing to the new memory to store the results, thus saving memory space and expanding the consumption of the underlying array. This will be very significant when the slice length is large enough.

The following examples are all operations performed on the memory space of the underlying array of slices. It should be noted that these operations will also change the underlying array while generating new slices on the underlying array.

Delete elements at the specified location

The following function deletes the element at index position i from the original slice

func remove(slice []int, i int) []int {
  copy(slice[i:], slice[i+1:])
  return slice[:len(slice)-1]
}

func main() {
  s := []int{5, 6, 7, 8, 9}
  (remove(s, 2)) // "[5 6 8 9]"
}

The built-in copy function makes it easy to copy one slice on another slice of the same type.

Filter elements

The following function filters out the slice elements that meet the conditions from the input source slice and returns a new slice composed of elements that meet the conditions.

type funcType func(T) bool //Represents the filtering logic function, which can be implemented as needed
func filter(a []T, f funcType) []T {
  b := a[:0]
  for _, x := range a {
   if f(x) { 
   b = append(b, x)
   }
  }
  return b
}

Reverse slices

func reverse(a []T) []T {
  for i := len(a)/2-1; i >= 0; i-- {
    opp := len(a)-1-i
   a[i], a[opp] = a[opp], a[i]
 }
 
 return a
}

Group slices

The following function receives a []int type source slice actions and returns a nested slice grouped by a specified length (it's very difficult to explain. Students who have used PHP can understand it as the Go version of the array_chunk function. If you haven't used it, see the following example). Assume that the tiling value is: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, set the length batchSize of the element in the group to 3, and the slice after the group returned after the function call is [[0 1 2] [3 4 5] [6 7 8] [9]]

func chunk(actions []int, batchSize int) []int {
 var batches [][]int

 for batchSize < len(actions) {
   actions, batches = actions[batchSize:], append(batches, actions[0:batchSize:batchSize])
 }
 batches = append(batches, actions)
 
  return batches
}

func main() {
 actions := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
 batchSize := 3
  chunks = chunk(actions, batchSize)
  //chunks is [[0 1 2] [3 4 5] [6 7 8] [9]]}

By the way, the complete slice expression is as follows:

input[low:high:max]

The last max does the role of the generated slice, the cap (capacity) is max - low.

In-situ deduplication (only for comparable slice types)

import "sort"

func main() {
 in := []int{3,2,1,4,3,2,1,4,1} // any item can be sorted
 (in)
 j := 0
 for i := 1; i < len(in); i++ {
    if in[j] == in[i] {
      continue
 }
 j++

 in[j] = in[i]
 }
 result := in[:j+1]
 (result) // [1 2 3 4] 
}

Some examples in the article come from golang's official GitHub wiki. This wiki introduces many slice usage tips. Learn more about golang's GitHub wiki/golang/go/wiki/SliceTricks#filtering-without-allocating

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.