e-commerce компания Юго- Восточной Азии • Работает в 6 странах Юго-Восточной Азии с суммарным населением 650M человек • Более 40 миллионов продуктов • 1.2M товаров за время последней распродажи (3 дня) • С 2016 года является частью Alibaba Group
виде, в котором они реализованы в таких языках, как Java или С++. В данном докладе будет описано, какие проблемы решаются с помощью перечисляемых типов, как перечисляемые типы реализованы в других языках и какие подходы и инструменты можно использовать в Go, чтобы получить все преимущества от использования Enum.
значений представляет собой ограниченный список идентификаторов. - https://en.wikipedia.org/wiki/Enumerated_type Пример: месяцы в году, дни недели, планеты Солнечной системы.
компилятора: В данном случае переменной planet будет присвоено некорректное значение 42 nibiruPlanet := 42 var planet int if isFromPlanet("Mars”) { planet = Mars } else { planet = nibiruPlanet } Константы не типобезопасны
перечисление более типобезопасным, но не ограничивает список этих значений. Мы все еще можем присвоить нашему типу некорректное значение: cannot use nibiruPlanet (type int) as type Planet in assignment nibiruPlanet := 42 var planet Planet planet = Mars // ok planet = Planet(nibiruPlanet) // преобразование типа planet = 42 // числовой литерал
данном случае полю структуры HomePlanet будет присвоено некорректное значение по умолчанию - 0. type Spaceship struct { Name string Captain string HomePlanet Planet } Enterprise := Spaceship{ Name: "USS Enterprise", Captain: "James T. Kirk", HomePlanet: Earth, } UFO := Spaceship{ Name: "Unknown", }
логике ветвления, например, в switch операторе: При добавлении нового значения в перечисляемы тип можно легко забыть о том, что нового значение нужно обработать в разных местах кода. switch p { case Mercury: return "Mercury" case Venus: return "Venus" case Earth: return "Earth" case Mars: return "Mars" }
ошибку: Day today = Day.SUNDAY; switch (today) { case Day.MONDAY: System.out.println("Mondays are bad."); break; case Day.FRIDAY: System.out.println("Fridays are better."); break; case Day.SATURDAY: case Day.SUNDAY: System.out.println("Weekends are best."); break; } ERROR at line 16, col 1: switch must be exhaustive, consider adding a default clause } ^
uranus, neptune } В Swift можно также описывать перечисляемые типы с "сырым" (raw) значением: enum Planet: Int { case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune }
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune } var planet = Planet.earth planet = 42 ERROR at line 7, col 10: cannot assign value of type 'Int' to type 'Planet' planet = 42 ^~ Planet(rawValue: )
значение в перечисляемый тип: enum Planet: Int { case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune } let positionToFind = 42 if let somePlanet = Planet(rawValue: positionToFind) { switch somePlanet { case .earth: print("Mostly harmless") default: print("Not a safe place for humans") } } else { print("There isn't a planet at position \(positionToFind)") }
ошибку: var planet = Planet.earth switch planet { case .mercury: print("Lots of planets have a north") case .venus: print("Watch out for penguins") case .earth: print("Where the sun rises") case .mars: print("Where the skies are blue") } ERROR at line 16, col 1: switch must be exhaustive, consider adding a default clause } ^
Scientist } fn main() { let mut person = Person::Engineer; let _ = Person::Scientist; // используем пустой // идентификатор чтобы // скомпилировалось J person = 42; match person { Person::Engineer => println!("Is an engineer!"), Person::Scientist => println!("Is a scientist!") } } error[E0308]: mismatched types --> <anon>:9:9 | 9 | person = 14; | ^^ expected enum `Person`, found integral variable | = note: expected type `Person` found type `{integer}`
перечисляемыми типами? • Типобезопасность • Защиту от присвоения перечисляемому типу некорректного значения • Проверки на обработку всех значений перечисляемого типа в switch операторах • Автоматическое получение строкового представления • Интеграция с json/yaml/csv ...
Banana ) ... var f Enum f = 42 // line 1 f = Enum(42) // line 2 $ enumlinter -type Enum ./enum.go:1:6: Enum type constant must be used instead of a basic literal “42” ./enum.go:2:6: converting function must be used instead of type casting “Enum(42)”