Go: Можете ли вы использовать диапазон со срезом, но получить ссылки?(Итерация) - PullRequest
4 голосов
/ 09 февраля 2011

Скажем, я хочу изменить значение для всех объектов в массиве.Мне нравится синтаксис диапазона намного больше, чем просто имя для циклов.

Поэтому я попытался:

type Account struct {
   balance int
}
type AccountList []Account
var accounts AccountList
...
....
// to init balances
for _,a := range( accounts ) {
    a.balance = 100
}

Это не сработало, поскольку a является копией записей из AccountList, и мыТаким образом, обновляются только копии.

Это работает так, как мне нужно:

for a := range( accounts ) {
  accounts[a].balance = 100
}

Но этот код имеет дополнительный поиск внутри цикла for.

IsЕсть ли способ сделать итератор, который получает ссылки на структуры в AccountList?

Ответы [ 2 ]

3 голосов
/ 11 февраля 2011

Проблема в том, что, используя ваш первый цикл for / range, вы получаете значение struct by-value в переменной a.Второй цикл for / range, который вы использовали, решает проблему, напрямую обращаясь к памяти в срезе.

Однако вы неверно утверждаете, что во втором цикле for происходит «дополнительный» поиск.Условие цикла просто собирается проверить длину среза и увеличивать счетчик до тех пор, пока он не достигнет конца.Затем выражение accounts[a] будет фактически выполнять поиск в массиве и напрямую манипулировать памятью.Во всяком случае, второй цикл for преобразуется в меньшее количество инструкций, поскольку он не копирует содержимое struct by-value в первую очередь.

Я думаю, что вас беспокоит то, что вам нужно сослаться на accounts[i]каждый раз.Если вы хотите выполнить несколько манипуляций с учетной записью внутри цикла for, я думаю, что наилучший способ ее решения будет выглядеть следующим образом:

for i := range accounts {
    a := &accounts[i]
    a.balance = 100
    // manipulate account A further...
}

Другое возможное решение, как предложила Мью, это просто иметьломтик держит указатели.Есть преимущества у любого из способов сделать это, но дилемма одна и та же, независимо от того, находитесь ли вы в C или Go.Иди просто немного больше синтаксического сахара.

3 голосов
/ 09 февраля 2011

Просто пусть AccountList будет [] * Account. Затем вы получите указатели на каждую учетную запись в пределах диапазона.

...