Pull to refresh

Comments 26

Вот бы go generate вызывался бы автоматически, при изменении зависимых файлов.
Короче хочу make
Ну Make вам никто не мешает использовать. До go generate, в основном, подобная задача решалась именно мейкфайлами, да и сейчас, некоторые их, по привычке, используют с Go. Хотя большая часть проектов, безусловно, стараются, чтобы workflow был стандартным — go generate/build/test.

И, как написано в статье, если вы «заставите» всех пользователей вашего пакета регенерировать файлы на каждом билде — с большой вероятностью, они получат ошибку, так как у них могут быть не установлены нужная программа-генератор. Все таки, это функция автора(ов) пакета.
Т.к. кто-нибудь должен будет написать коммент, что программирование в комментах — это плохо, то это сделаю я.
Но я ещё более радикален, не приемлю в принципе зависимость логики программы от форматирования файла с исходным кодом. Поэтому, для меня кодогенерация из комментов и вложенность блоков по табуляции кажутся одинаково опасными штуками.
С табуляцией всё не так страшно, поскольку вы её в любом случае ставите, даже в языках, где она ни на что не влияет.

В целом, имею положительное отношение к Go, но подобные моменты, типа магических комментариев, макросов, прикрученных сбоку (go generate), отсутсвие (ненужных, ага) генериков, немного огорчают. К тому же, могли бы добавить пилюлю от NPE, в 21-м веке-то (здесь нравится подход Kotlin с Int и Int?).
В том-то и дело, что они лишь кажутся такими, потому что вы смотрите с перспективы других языков. Я полностью согласен, что есть хорошие и плохие практики, и «специальных комментарии» — одна из как-бы не очень хороших практик, хотя я сходу не вспомню, где это действительно приводило к проблемам.

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

Аналогично и с go generate — мне не встречался ни один случай, где факт того, что go generate описывается комментариев приводил к какой-либо проблеме или путанице. Если вы пишете на Go и для вас это стало проблемой — расскажите, интересно же.
По факту, это практично и удобно, это обратно совместимо и не приводит к непоняткам.

Так что, если не вешать раньше времени ярлыки, а попробовать в деле — то всё окажется не таким, как кажется поначалу.
> и «специальных комментарии» — одна из как-бы не очень хороших практик
Называйте вещи своими именами. Это просто _плохая практика_.
Называйте вещи своими именами. Это просто _плохая практика_.

Это здорово, что вы знаете что такое «плохие практики». И уверен, вы не слепо навешиваете ярлыки, без понимания их сути.
Расскажите, пожалуйста, какие проблемы ждут Go-программистов из-за такого дизайна go generate?
Смешение понятий не сразу проявляется явными проблемами. Сначала комментарии становятся не совсем комментариями и все это принимают как должное. А потом никто уже не удивляется, что подобных «исключений» накапливается столько, что назвать это чистым дизайном просто язык не повернётся.
Если go generate так уж нужно конфигурировать из мета-информации, то это должна быть мета-информация со своим явным синтаксисом. А комментарии оставьте тем, чем они и должны являться.
Знаете, что мне нравится в Go, так это то, что я могу быть уверен, что его ядром занимаются люди в разы умнее и опытнее меня. Я бы себя посчитал крайне наивным, если бы стал заявлять, что я «вижу очевидный минус, который авторы Go просто не заметили или не додумались». Мне это, кстати, помогло очень быстро пройти эти этапы «WTF, да какое право они имеют мне говорить, что неиспользуемый импорт — это ошибка!». И я очень благодарен такой «радикальности» многих решений Go — они, за меня, заставили меня писать код лучше и чище, не игнорировать ошибки, писать тесты и так далее. Зная, что именно так и задумывалось, я считаю это бесценным — умение смотреть далеко вперед и помогать программистам стать лучше с помощью дизайна языка и тулинга.

К чему это всё я. К тому, что если появится надобность дописать ещё что-то в «специальные комментарии», а уж тем более, если не раз — то и авторы Go и коммьюнити — в котором тоже немало очень толковых людей — среагируют, обсудят и предложат более оптимальное решение, найдя наиболее правильный компромисс. С существующей системой пропозалов и open-source модели Go такой вклад может сделать любой, вобщем-то — авторы Go лишь будут следить, чтобы изменения следовали основной идее Go. Вобщем, чего-чего, а мысль о том, что в Go в комментариях появится каша из всего чего угодно, и всем будет на это наплевать — я не верю. Слишком хорошо знаю людей, которые за этим стоят — в том числе, по личному общению на конференциях.
Я потому где-то уже и писал, что все же считаю это временным решением, которое однажды перетечёт в другую форму (и придётся поддерживать обратную совместимость). Или не перетечёт, т.к. уже много всего будет написано именно так (привет, пхп).
Не хочу снова холиварить насчёт неиспользуемого импорта. Конечно, IDE могут научиться сами комментировать импорт, если закомментирован код отладки. Что прибивает разработчика гвоздями к конкретной IDE.
В общем итоге, никто не пытается выставить Go в свете какой-то непроработанности (точно уж не я). Но я призываю поддерживать тех, кто вытягивает всяческие кривульки из тени под лампы прожекторов и говорит ясно и честно: это не лучшее решение.
Не хочу снова холиварить насчёт неиспользуемого импорта.

Да нечего тут холиварить — это исключительно привычка. Вы давно на Go пишете? Просто у практически всех эта фича становится любимой — она *гарантирует*, что у вас не будет кучи лишних импортов, вы уверены, что их не будет ни в чьем коде и т.д. — это big deal на самом деле, ворнинги такой эффект не дадут. А во время отладки поставить _ или удалить импорт — оказывается совсем несложно, особенно, если используется goimports, который сам добавляет/удаляет импорты и его вешают на save-хук, вместо go fmt (он drop-in замена go fmt по сути).

Но я призываю поддерживать тех, кто вытягивает всяческие кривульки из тени под лампы прожекторов и говорит ясно и честно: это не лучшее решение.

Тут я только за. Но за объективную дискуссию, а не за «ну это же очевидно, что это плохо, потому что плохо» :) А если уж и обсуждать дизайн, то это должны делать люди, которые, как минимум, знакомы с Go.
Я, кстати, тоже думаю, что если бы потребность в go generate заложили до релиза 1.0, то, возможно, было бы иное решение (хотя мне сложно предположить — какое, нынешний дизайн go generate реально всех устраивает и отлично выполняет свою функцию). Но один из посылов дизайна было — «it must fit well with the existing go command», и это, конечно, важный фактор.
Или можно пойти по пути джавы, которая сама удаляет неиспользуемые импорты при компиляции, но это потеря скорости компиляции, которой go заслуженно гордится.
Кстати, хочу отдать вам должное. Вы принимаете существенные усилия для популяризации и защиты Go в русскоязычном сообществе, хотя он и сам по себе достаточно заметный язык.
Спасибо. Комментаторы на хабре, конечно, иногда отбивают это желание, но я, все-таки, получаю некоторое удовольствие — переводить мне легко, идею Go я очень хорошо чувствую нутром (она совпадает с моими собственными взглядами), плюс переводы заставляют внимательней углубляться даже в темы, которые, казалось бы я для себя давным давно уже закрыл. Вобщем, сплошная польза ) А если ещё и кому-то это полезней (не все ж, наверное, англоязычные ресурсы легко читают), то тем более хорошо.
А в чём преимущества "//" перед каким-нибудь другим символом? Каковы причины использования «магических комментариев» а не отдельного синтаксиса?
Я так понимаю, отдельный синтаксис/сущность — это усложнение грамматики, усложнение языка, лишнее и не нужное. Его плюсы никак не перевешивают минусов. Плюс нарушается прямая совместимость — код «с новым синтаксисом» нельзя будет собрать на предыдущей версии (это не критично, гарантируется только обратная совместимость, но всё же, если можно этого избежать, лучше избегать).
Кроме того, специальные комментарии в Go давно использовались, и выполняют свою функцию отлично, никаких проблем с ними нет.
Лишняя сущность уже есть. А использовать для нее существующий синтаксис, это все равно использовать для умножения плюс с особым синтаксисом. Не считаю что это упрощает язык. Нарушения прямой совместимости в развивающемся языке это не страшно ИМХО.
В том, что обработкой этих специальных комментариев и генерацией кода занимается вовсе не компилятор, а отдельная утилита. Поэтому для компилятора это не является какой-либо синтаксической конструкцией, от которой зависит результат компиляции. На момент запуска компилятора весь код уже должен быть сгенерирован.
Ну тогда берем любой символ — например '@'. Не знаком с синтаксисом go слишком уж основательно, потому предположу, что этот символ еще никак не задействован. И пусть компилятор воспринимает строки начинающиеся с этого символа как комментарии — как #pragma в C++, после которой может в принципе быть написано что угодно.
Какие у этого подхода минусы, кроме сломанной прямой совместимости?
Очевидный минус вы сами назвали — код с таким синтаксисом несовместим со старыми версиями компилятора, а на данный момент в go кодогенерация полностью независима от процесса компиляциии и работает для всех версий go (например, если я использую go 1.0 и установлю пакет, разработчик которого использовал go generate доступный с go 1.4, то проблем не будет).

"#pragma" в C++ всё-таки обрабатывается на стадии препроцессинга, который является одним из этапов компиляции. А go generate полностью отделён от компиляции и является внешним по отношению к языку инструментом.
Раз уж мы засовываем директивы внешнего инструмента прямо в код, то пусть компилятор их учитывает.
Альтернатива — отдельный файл GENERATE например с содержанием по типу:
stringer -type=Pill
Ну вы же и сами видите в каждом вами предложенном варианте минусы, правда?
ИМХО — внешняя утилита «полностью отдельная от компиляции» должна иметь свои отдельные файлы.
А если по каким то причинам мы не хотим делать так, а хотим чтобы добавить новую сущность в файлы исходников, то нежелание при этом менять компилятор выглядит странно. Если уж добавляем новую сущность в исходники, то изменение при этом компилятора никак не может считаться минусом — это необходимость.

Можно было закодировать go generate whitespace'ами — их ведь тоже компилятор не учитывает. Но это костыль, как и магические комментарии, и вставлять его на относительно раннем этапе развития языка довольно странно.
То что добавлено в компилятор должно там оставаться, а тут какие-то магические паттерны (как тут верно замечали go generate просто ищет подстроки), и внешняя тулза, может и потеряться в следующей мажорной версии.
А серьезно — не стоит делать чтобы компилятор сам запускал какие-то программы на неограниченном кол-ве пакетов (go generate я напоминаю надо запускать только в своих), там какой нить шутник может и rm -rf написать.
Так что правильно критиковать наличение go generate как такового.
Давайте посмотрим теперь на пример, что предлагает Пайк:

//go:generate go tool yacc -o gopher.go -p parser gopher.y
ну тут понятно, есть грамматика, создаем парсер, ок.

//go:generate stringer -type=Pill
то есть по сути попробовали добавить штуку, чтобы более менее одинаково люди писали свои обобщенно-программируемые кодогенерации, а не так например:
// +gen stringer
type Pill strunct {

}
Каждый раз, когда мы меняем определение Pill или констант, всё что мы должны сделать, это запустить $ go generate
Почему это нужно делать вручную? Это так задумано или просто недоработка?

Второй вопрос можно легко предвосхитить: почему это было сделано через комментарии? Комментарий может быть где угодно в коде? А что будет если написать такой комментарий несколько раз в разных местах программы? Атрибуты (как в Rust) выглядят красивее как минимум (не знаю, насколько такое применимо и оправдано в случае Go, но активные комментарии выглядят всё равно странно).
В Go специальные комментарии были с самого начала — для тегов сборки. Мне не известно о каких-либо проблемах с этим, напротив — подход convention over configuration себя показал в Go с хорошей стороны. Видимо поэтому, решили для go generate и не плодить новые сущности и фичи языка, а воспользоваться проверенным и удобным способом.
Sign up to leave a comment.

Articles