company_banner

4 примера iota-перечислений

Автор оригинала: yourbasic.org/golang
  • Перевод


От переводчика: при разработке ПО у программистов, какого бы уровня они ни были, нередко возникает желание реализовать тот или иной фрагмент программы более красиво и удобно. Когда, глядя на код, интуитивно чувствуешь: этот кусок точно можно сделать изящнее, начинаешь либо вспоминать best practice для решения таких задач, либо искать их в инете, либо придумывать своё решение. Недавно я сам столкнулся с подобной ситуацией и нашёл, казалось бы, очевидное решение, но, тем не менее, ранее я им не пользовался. Вот им бы хотелось поделиться с сообществом в представленном ниже переводе очень небольшой статьи.


Базовый пример iota


  • Ключевое слово iota представляет последовательные целочисленные константы 0, 1, 2,…
  • Оно обнуляется каждый раз, когда const появляется в исходном коде
  • И увеличивается после каждой спецификации const.

const (
    C0 = iota
    C1 = iota
    C2 = iota
)
fmt.Println(C0, C1, C2) // "0 1 2"

Можно упростить до:


const (
    C0 = iota
    C1
    C2
)

Тут полагаемся на то, что выражения неявно повторяются в объявлении const в скобках — это указывает на повторение предыдущего выражения и его тип.


Начать с единицы


Чтобы начать список констант с 1 вместо 0, можно использовать iota в арифметическом выражении.


const (
    C1 = iota + 1
    C2
    C3
)
fmt.Println(C1, C2, C3) // "1 2 3"

Пропустить значение


Можно использовать пустой идентификатор, чтобы пропустить значение в списке констант.


const (
    C1 = iota + 1
    _
    C3
    C4
)
fmt.Println(C1, C3, C4) // "1 3 4"

Полный тип enum со строками [best practice]


Вот идиоматический способ реализации перечисляемого типа:


  • создаем новый целочисленный тип,
  • перечисляем его значения с использованием iota,
  • реализуем для типа функцию String.

type Direction int

const (
    North Direction = iota
    East
    South
    West
)

func (d Direction) String() string {
    return [...]string{"North", "East", "South", "West"}[d]
}

В действии:


var d Direction = North
fmt.Print(d)
switch d {
case North:
    fmt.Println(" goes up.")
case South:
    fmt.Println(" goes down.")
default:
    fmt.Println(" stays put.")
}
// Output: North goes up.

Соглашение об именовании


По стандартному соглашению об именовании, необходимо использовать смешанный caps и для для констант. Например, экспортируемую константу будет правильным назвать NorthWest, а не NORTH_WEST.


Что почитать по теме


Другое распространенное приложение для iota — реализация bitmask. Это небольшой набор булевых значений (их часто называют “флагами”), которые представлены битами в одном числе.


Посмотрите bitmasks и флаги для полного понимания.


Также читайте другие статьи в нашем блоге:


Nixys
Эксперты в DevOps и Kubernetes

Похожие публикации

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

    +3

    Если уже речь заходит о best practices, то я бы рекомендовал в большинстве случаев избегать случайного совпадения zero-значения с одной из констант:


    const (
        _ Direction = iota
        North
        East
        South
        West
    )

    Плюс использовать кодогенерацию через stringer вместо ручной реализации метода String.

      +2

      Такой вариант — качественно не то же самое?


      const (
          North Direction = iota + 1
          East
          South
          West
      )
        +1

        То же. Вопрос вкуса, мне первый вариант нравится больше — там явно отделены все константы и нельзя случайно потерять "+ 1".

      +1
      Еще, мне кажется, для полноты понимания работы было бы неплохо упомянуть о поведении в случаях нескольких iota в одной строке:
      const (
      	a = iota
      	_ = iota
      	b, c = iota, iota
      )

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое