Как реализовать изменяемые размеры массивов в Go - PullRequest
52 голосов
/ 02 августа 2010

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

type a struct {
    b int
    c string
}

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

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

Ответы [ 5 ]

57 голосов
/ 12 августа 2010

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

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

Переменная s представляет собой слайс с длиной 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)

Документ Effective Go продвигает этот пример немного дальше, реализуя функцию Append, которая добавляет один фрагмент к другому, изменяя его размер при необходимости.

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

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

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

56 голосов
/ 02 августа 2010

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

Пример:

type mytype struct {
  a, b int
}

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

Обратитесь к spec за дополнительной информацией о приложении.

19 голосов
/ 14 июня 2011

Идиоматический способ сделать это изменился.Добавление встроенной функции 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

1 голос
/ 09 августа 2010

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

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

код будет

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
  }
}
0 голосов
/ 05 сентября 2018

Привет, мы можем просто сделать это двумя способами

type mytype struct {
  a, b int
}

Просто сделай так

  1. Без добавления

__

a := []mytype{mytype{1, 2}, mytype{3, 4}, mytype{4, 5}}
  1. с добавлением

__

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

Добавьте столько, сколько хотите. Первый - это простой способ сделать это. Надеюсь, это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...