навыки применения памяти golang slice

Go

Нарезка — это очень часто используемый агрегатный тип в языке Go, он представляет собой последовательность переменной длины, а лежащий в основе объект ссылается на объект массива. Срез состоит из трех частей: указателя, длины и емкости. Указатель на адрес памяти базового элемента массива, соответствующего собственному первому элементу среза.

Объявление типа среза выглядит следующим образом:

type slice struct {
  array unsafe.Pointer
  len   int
  cap   int
}

Данные базового массива могут совместно использоваться несколькими слайсами, а диапазоны массивов, на которые ссылаются, могут перекрываться. Используя эту функцию слайсов, мы можем выполнять такие операции, как инверсия, фильтрация и дедупликация слайсов в исходном пространстве памяти, так что нет необходимости объявлять слайс, указывающий на новую память, для сохранения результатов, тем самым экономя место в памяти и расширение потребления базового массива, что очень эффективно, когда длина среза достаточно велика.

В следующих примерах показаны все операции, выполняемые над пространством памяти нарезанного базового массива.Следует отметить, что эти операции генерируют новые срезы на базовом массиве, а также изменяют базовый массив.

удалить элемент в указанной позиции

Следующая функция удаляет позицию индекса из исходного среза.iЭлементы на

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}
    fmt.Println(remove(s, 2)) // "[5 6 8 9]"
}

Встроенная функция копирования упрощает копирование слайса на другой слайс того же типа.

элемент фильтра

Следующая функция отфильтровывает элементы среза, удовлетворяющие условию, из среза входного источника и возвращает новый срез, состоящий из элементов, удовлетворяющих условию.

type funcType func(T) bool //代表筛选逻辑函数,可以按需实现

func filter(a []T, f funcType) []T {
    b := a[:0]
    for _, x := range a {
	    if f(x) { 
		    b = append(b, x)
	    }
    }
    return b
}

Обратный срез

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
}

сгруппированные фрагменты

Следующая функция получает[]intтип исходного фрагментаactions, возвращает вложенный слайс, сгруппированный по заданной длине (это сложно объяснить, студенты, которые использовали PHP, могут понять это как версию Goarray_chunk 函数, см. пример ниже, если он не использовался). Предположим, что значение фасета равно:[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, задайте длину элементов в группеbatchSizeравно 3, сгруппированный срез, возвращаемый после вызова функции,[[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 为[[0 1 2] [3 4 5] [6 7 8] [9]]
}

Здесь, кстати, полное выражение среза имеет вид:

input[low:high:max]

Эффект последнего максимума заключается в том, что кепка (емкость) сгенерированного слайса равнаmax - low.

Дедупликация на месте (только для сопоставимых типов слайсов)

import "sort"

func main() {
	in := []int{3,2,1,4,3,2,1,4,1} // any item can be sorted
	sort.Ints(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]
	fmt.Println(result) // [1 2 3 4] 
}

Некоторые примеры в статье взяты из официальной вики-страницы GitHub golang, которая знакомит с множеством навыков нарезки.GitHub.com/gowaves/go/me…