Подтвердить что ты не робот

Как реализовать масштабируемые массивы в Go

Я исхожу из фона С++, и я привык использовать класс std::vector для таких вещей. Предположим, что мне нужен динамический массив из них:

type a struct {
    b int
    c string
}

Каков стандартный способ сделать это?

Фрагмент будет очень полезен

4b9b3361

Ответ 1

Используйте append() встроенный

Пример:

type mytype struct {
  a, b int
}

func main() {
  a := []mytype{mytype{1, 2}, mytype{3, 4}}
  a = append(a, mytype{5, 6})
}

Обратитесь к spec для получения дополнительной информации о добавлении.

Ответ 2

A Go Slice содержит три элемента: данные, длину и емкость.

s := make([]int, 0, 10)

Переменная s представляет собой фрагмент int с длиной 0 и емкостью 10. Встроенные функции len() и cap() позволяют получить длину и емкость среза:

len(s) == 0
cap(s) == 10

Чтобы увеличить длину фрагмента, просто повторите фрагмент:

s = s[0:5]
// len(s) == 5
// cap(s) == 10

Чтобы уменьшить длину, вы можете взять суб-срез:

s = s[0:1]
// len(s) == 1

Есть несколько более коротких способов вызова make():

a := make([]int, 10) 
// len(a) == cap(a) == 10

b := make([]int)
// len(b) == cap(b) == 0

Это все хорошо и хорошо, но что, если вам нужно увеличить длину кусочка, выходящего за пределы его возможностей? Для этого вам нужно выделить новый фрагмент и скопировать содержимое старого фрагмента в новый. (Функция "копировать" является другой встроенной.)

t := make([]int, len(s), 20)
copy(t, s)

Эффективный документ Go более подробно описывает этот пример, реализуя функцию добавления, добавляющую один срез к другому, при необходимости изменяя его размер.

Ломтики поддерживаются массивами; когда вы делаете() срез определенной емкости, массив этой емкости выделяется в фоновом режиме. Срез эффективно становится "умным указателем" на этот массив. Если вы передаете этот срез (или подсечку этого среза) другой функции, он передается как указатель на тот же массив. Это приводит к тому, что суб-срезы очень дешевы для создания - это распределение дорогостоящего массива поддержки.

Стандартная библиотека Go включает в себя несколько пакетов контейнеров - например, вектор, которые устраняют необходимость ручного управления срезами. Для удобства используйте срезы для скорости и более сложные классы контейнеров. (Говоря это, я все еще использую ломтики для большинства вещей.)

Вам может быть интересно, почему вам нужно идти на все эти неприятности. В конце концов, многие языки предоставляют динамически измененные массивы в качестве примитивов. Причина этого связана с философией Go. Разработчики языка не могут понять, какая политика распределения соответствует вашей программе; вместо этого они предоставляют вам инструменты, необходимые для создания собственных структур данных.

Ответ 3

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

type a struct {
    b int
    c string
}

func main(){
    var mySlice []a
    mySlice = append(mySlice,a{5,"pizza"})
}

Append() добавит данный элемент в срез, если есть место или растянуть срез, если он не будет достаточно большим.

Дополнительная информация о append() находится здесь http://golang.org/doc/go_spec.html#Appending_and_copying_slices

Ответ 4

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

Верхняя сторона состоит в том, что срез [] Int может быть просто проиндексирован как массив и будет возвращать int при использовании таким образом.

Недостатком является то, что он не будет автоматически расти в пределах своей заявленной емкости. Эффективный путь содержит пример того, как вы будете обращаться с перераспределением.

код будет

type mytype struct {
   a, b int
}




func main() {

  sl := make([]mytype, 10, 50) //slice of 10 items, max capacity 50 these do not have to be constant expressions.
  sl[0] = mytype{1,2}
   //...
  for i, value := range sl {
  // ... do stuff with value
  }
}