Гошный путь: просто, быстро, но не то

Type switch по дженерик типу с жёстким constraint -❌ Type switch по any c любым типом в рантайме -✅

Для меня совершенно не очевидным был тот факт, что первый вариант в Go невозможно реализовать без костылей (без приведения к any или, не дай бог, рефлексии), что меня немало расстроило.

Почему-то казалось, что ничего нового быть не может, а под капотом такая же привычная и прямолинейная механика, как и С++ с их template class. Они работают через полное мономорфизирование: для каждого конкретного T компилятор генерирует отдельный код (копипастит с подстановкой типа). На выходе можно делать "всякое", ведь компилятор "видит" точный тип на этапе компиляции.

А все потому-что разработчики Go пошли несколько иным путем в реализации дженериков. Сonstraints - это просто контракты, а не инструкции для генерации кода. Следовательно, компилятор не может сгенерировать type switch, потому что type switch основан именно на runtime type, а для T его как бы "не существует".

Разрабы Go хотели выпендрится таким образом? Вряд-ли. С точки зрения преимуществ, которые мы получаем, все круто:

  • меньше рост бинарника (не копипастим)
  • компиляции шустрее

Даже если опустить эту досадную неприятность с type switch, которая меня привела в текущую точку, все еще остается одна важная вещь, из-за которой я не могу сказать - "гошные дженерики заебись". На дженериках в Go невозможно "думать"!

Объясняю: в C++ template class - мощный инструмент метапрограммирования, который позволяет:

  • Использовать свойства типа на этапе компиляции. А еще можно писать ОЧЕНЬ оптимизированные и специализированные штуки под разные типы данных. В C++ std::vector и std::vector - реально разные классы на уровне байтиков!
  • Поскольку весь код "разворачивается" компилятором, никакой обёртки через interface{} или runtime-dispatch не нужно, что == zero-cost abstraction

С точки зрения стоящей передо мной задачи (а именно развитие DSL), где как никогда было бы полезно перенести в compile-time значительную часть логики, дженерики Go оказались практически бесполезными. Как итог, чересчур много runtime проверок там, где это можно было бы исключить на этапе компиляции.

Гошный путь: просто, быстро, но не то
Type switch по дженерик типу с жёстким constraint -❌
Type switch по any c любым типом в рантайме -✅
Для меня совершенно не очевидным был тот факт, что первый вари... | Сетка — социальная сеть от hh.ru