Как использовать ненулевые индексы и 0-индексированные списки

# #go

Вопрос:

Если я передаю значение int в структуре (в моем конкретном случае, аргументы rpc), язык не позволяет, чтобы атрибут был равен нулю. Пустое значение для int равно 0.

Но Go использует 0-индексированные массивы. Мне нужен способ отличить пустое значение от индекса 0. Существует ли идиоматическое решение этой проблемы?

 // this is psuedo-code I had written before hitting this problem
if (args.maybeIndex != nil) {
  doSomething(sliceOfNodes[args.maybeIndex])
}
 

Ответ №1:

Если вы кодируете свои int по значению, то вы мало что можете с этим поделать — значение по умолчанию равно 0.

Распространенным способом обеспечения возможности обнуления в кодировках в Go является использование типов указателей. Использование a *int вместо an int позволяет различать «нет» и 0.

Например, на примере JSON рассмотрим структуру:

 type Options struct {
  Id      *string `json:"id,omitempty"`
  Verbose *bool   `json:"verbose,omitempty"`
  Level   *int    `json:"level,omitempty"`
  Power   *int    `json:"power,omitempty"`
}
 

И эти данные:

 {
  "id": "foobar",
  "verbose": false,
  "level": 10
}
 

Обратите внимание, что «мощность» не указана. Вы могли бы написать десериализатор:

 func parseOptions(jsn []byte) Options {
  var opts Options
  if err := json.Unmarshal(jsonText, amp;opts); err != nil {
    log.Fatal(err)
  }

  if opts.Power == nil {
    var v int = 10
    opts.Power = amp;v
  }

  return opts
}
 

Это устанавливает значение по умолчанию «мощность», если оно не указано. Это позволяет вам различать « power не присутствовал» и « power присутствовал, и его значение было 0″.


Если ваш механизм кодирования / RPC не допускает указателей, вы можете обойти это, создав другое логическое поле с именем «присутствует индекс» или что-то в этом роде.

Наконец, подумайте о разработке своей программы, чтобы сделать ее устойчивой к различиям между «не установлено» и «установлено значение по умолчанию». IOW, просто примите, что значения по умолчанию и неуказанные данные-это одно и то же. В долгосрочной перспективе это приведет к более чистому дизайну и коду и будет менее подвержено ошибкам.

Комментарии:

1. круто, спасибо за подробный ответ Илай. Очень полезно проверить эти подходы у кого-то с опытом. FWIW Я думаю, что ваш совет об устойчивости между двумя состояниями-лучший маршрут, так как моя проблема заключается только в первых нескольких вызовах, вероятно, моим решением будет какое-то состояние node.isReady.