Почему Go — это хорошо продуманный язык программирования

    В недавнем посте с критикой Go, который был выдан за перевод, пользователь tucnak, помимо избыточной фамильярности в адрес Роба Пайка, поднял несколько интересных моментов языка. Поскольку формат статьи предполагал, увы, не желание разобраться в теме, а разжечь холивары, предлагаю в этой статье пройтись по озвученным «проблемам» и понять, о чём же речь на самом деле, и что же заставляет современные компании выбирать Go.

    image


    Причина №1. Манипуляции со слайсами просто отвратительны


    Автор начинает свой разнос дизайна языка с утверждения о том, что отрицательные индексы, как в Python, не работают.
    // numbers[:-1] из Python не прокатит.

    Здесь ответ прост — Go это не Python, это разные языки. Некоторым людям сложно даётся факт, что никакие языки, кроме Питона, не являются Питоном, но давайте изучим вопрос детальнее. Вот официальный ответ Роберта Пайка о том, почему отрицательных индексов нет в Go:
    Это было убрано намеренно, потому что выражение s[i:j] может молча дать неверный результат, если j станет меньше нуля. Именно это было причиной ужасного бага в Rietveld, кстати говоря. Индексы должны быть не отрицательны.


    В issues на Github есть похожий вопрос и ответ, который дополняет следующим утверждением:
    Эта фича (присутствующая в Питоне, например) отсутствует намеренно.
    Арифметика с индексами в слайсах может приводить к проблемам, если ошибочный отрицательный результат «просто сработал», как обратный индекс. Это приводит к сложноуловимым багам

    Кроме того, от статус кво, выигрывает читабельность. Сейчас очевидно, что выражение s[:i] создает слайс от s длиной i байт. Если же i может быть отрицательным, то нужно больше контекста, чтобы понимать всё выражение слайса.

    Это решение отталкивается от общей философии Go избегать тонких синтаксических трюков.

    Можно согласиться, что кому-то для его случаев отрицательный индекс может быть удобен, и чуть короче в записи. Но авторы Go, исходя из своего, более чем, полувекового опыта разработки, видят, что эта экономия нескольких байт в одном случае, ведущая к сложным багам и ухудшению читабельности в другом — не стоит того, и выбирают решение, более подходящее концепции языка. Решение, требующее программистам на Python немного перепривыкнуть, но уменьшающее риск хитрых ошибок в long term. Понятно, что не все мыслят на long term, отсюда и конфьюз.

    Идем далее, следующий rant автора:
    / Хочется вставить какое-то число? Ничего страшного,
    // в Go есть общепринятая best practice!
    numbers = append(numbers[:2], append([]int{3}, numbers[2:]...)...)

    Во-первых, это не best practice а сниппет-однострочник, найденный на странице Go Slice Tricks. В реальном коде, если уж кто это и делает, то более читабельно. И тут мы, для начала, вспомним, что дизайн слайсов и массивов в Go обсуждался больше года, прежде чем прийти к окончательному дизайну. И основными факторами были «практическая необходимость» и «скорость». Да, это не очень привычный подход, во многих других языках наличие фич в большем приоритете, но в Go вот так.

    А теперь давайте спросим автора два вопроса:
    1. насколько частый случай — вставка элемента в середину массива?
    2. насколько эффективна вставка в середину массива?

    Думаю, не стоит пояснять, что при текущей реализации (массивы в Go очень похожи на массивы в C, и, в основном, служат хранилищем для слайсов) эта вставка — довольно дорогая операция, заставляющая (пере)выделять память, а реальный кейс использования этого не настолько частый, как, скажем «добавление» элемента к слайсу.
    Это и вправду совсем не частый кейс, по крайней мере в той нише, на которую рассчитан Go. Безусловно, такие кейсы есть — к примеру операции с бинарными протоколами, но это не то, что вы будете писать хотя бы раз в день или даже раз в месяц. В комментариях к посту автора я попросил хотя бы одного человека привести три примера из своего реального кода, где ему нужно было бы вставлять элемент в середину массива — не написал никто. Зато писали придуманные кейсы, в которых гораздо правильнее использовать не массивы, а более подходящие структуры данных.

    Резюмируя — такой дизайн выбран намеренно, для создания стимула правильно использовать структуры данных, и не получать в long term наследие в виде тормознутого софта. Опять же, видим этот ненавистный многим тут «long term», который портит всю сказку.

    Остальные комментарии к слайсам я разбирать не буду, они там уровня «а вот так в испанском пишут букву Н — смотрите какой ужас».

    Причина №2. Нулевые интерфейсы не всегда нулевые :)


    Это классический пример cherry-picking — автор находит в интернете пример кода, который может запутывать новичка, не знакомого с интерфейсами в Go (полагаю, большинство читателей предыдущей статьи), и выставляет этот пример, как «плохой дизайн». За кадром, конечно, остается то, что этому моменту посвящена запись в FAQ на странице Go, что в реальном коде с этой проблемой вы никогда не встретитесь (разве что, если вам совсем несмышленый джуниор попадется), и что дизайн системы типов и интерфейсов по своей простоте и целостности позволяет создавать сложнейшие абстракции без применения классов и наследования. Все это проходит мимо автора и его читателей, с восторгом пишущих «наконец-то пост ненависти про Go».

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

    Резюме — дизайн интерфейсов великолепен, и основан на сотне компромиссов из областей, о которых рядовой программист даже не слышал. В любом дизайне всегда будут мелкие или не очень вещи, которые могут сбивать с толку поначалу. Но в Go это единственная мелочь, с которой вы, скорее всего, на практике никогда не столкнетесь, и если уж и столкнетесь — то быстро найдете ответ в официальном FAQ, и никогда больше не ошибетесь. Мало языков таким могут похвастаться, и это одно из явных доказательств того, что дизайн Go продуман более, чем отлично.

    Причина №3. Забавное сокрытие переменных


    Тут автор, обманывает и читателей и самого себя. Во-первых, shadowing всегда был источником различных конфьюзов и непоняток, и в Go, в отличие от, скажем С++, нет undefined behavior при сокрытии переменных. Винить можно только невнимательность программиста, что, безусловно, не снимает с языка ответственности в том, чтобы помогать программисту не совершать такие ошибки.
    Во-вторых, критика «дизайна сокрытия переменных» должна подразумевать предложение альтернативного, более удачного дизайна — тогда дискуссия имеет шанс быть предметной.
    В-третьих, штатная утилита go vet умеет показывать сокрытые декларации переменных, но, поскольку сокрытие это не ошибка, то, по умолчанию этот флаг go vet выключен, чтобы не засорять вывод на правильном коде.
    Используйте
    go tool vet -shadow=true
    и не вводите в заблуждение читателей.

    Например на код автора оригинальной статьи, go vet скажет:
    
    $ go tool vet -shadow=true main.go
    main.go:16: declaration of number shadows declaration at main.go:10:
    

    Очевидно, что это не означает ошибки — по большей части, сокрытие переменных делается сознательно и код делает именно то, что хотел разработчик.

    Так что, как только вы начнете писать на Go, сами поймете, что в нормально структурированном коде проблем, еще и специфических для Go, с сокрытием не возникает.

    Причина №4. Ты не можешь передать []struct как []interface


    На эту ситуацию я, в начале знакомства с Go, наткнулся сам. Пытался делать нечто замудренное, по незрелости, конвертировать интерфейсы туда-обратно, и возникла вот точно такая же задача.
    Разумеется, я наткнулся на ошибку компилятора, но, в отличие от автора статьи, не бросился писать статью с проклятиями в адрес Пайка и утверждениями о том, что «в Go нет полноценной поддержки интерфейсов» (хаха), а нашел объяснение почему такая операция явно не поддерживается.
    Первое, что нужно знать — это отличия «структуры» от «интерфейса» в Go. Это просто, и этого достаточно, чтобы понять, почему вы просто так не можете «скастить» слайс структур в слайс интерфейсов. Это база, причем очень простая, и оправданий не знать её нет — вся документация на официальном сайте и читается за вечер.
    Второе — и созвучное с выше обсужденными слайсами — это то, что операция конвертирования слайсов — дорогая операция. По времени это O(n) и компилятор Go подобные дорогие вещи не будет делать, чтобы не давать нерадивым программистам писать медленный код. Хотите делать потенциально дорогую операцию — будьте добры, сделайте это явно, вся ответственность на вас, а не на компиляторе. Очень правильный подход, который нацелен на качество кода на Go в long term. Ну, ясно, почему для автора поста это так непонятно.

    Причина №5. Неочевидные циклы «по значению»


    Тут автор возмущается тем, что ключевое слово range передает значения, а не ссылки, и что, цитирую,
    range — это тебе не foreach из С++
    Потом, правда, поправляется и говорит, что проблема в том, что в документации явно это не указано.

    Что тут можно сказать? Go — это другой язык, это не C++. Зачем пытаться сделать из Go то Python, то C++ — загадка.
    Любой, кто прошел go-tour увидит в этой строке оператор ":=", который означает создание новой переменной и присвоение ей значения:
    for number := range numbers {}


    Никто не спорит, что плохо выспавшийся не очень внимательный новичок может решить, что range это тоже самое, что и foreach, и ошибиться. Но одного раза достаточно, чтобы понять свою ошибку и не афишировать свою невнимательность. Называть это «плохим дизайном языка» — чрезвычайно глупо, согласитесь.

    Причина №6. Сомнительная строгость компилятора


    Сомнительная строгость, по мнению автора заключается в том, что в Go код не компилируется если есть неиспользуемый импорт. Это, помимо того, что является квинтессенцией opinionated подхода Go к вопросу качества кода, ещё и демонстриует, что автор таки не читал FAQ, в котором этот вопрос подробно объяснен. Любой, кто писал на С/C++, знает во что превращаются проекты, после того, как кодом поработают 5-10 программистов, и код пройдет несколько стадий рефакторинга. Помимо этого, каждый импорт — это замедление процесса компиляции, и там где Go-программисты не успевают моргать глазом, С++-программисты идут пить кофе и ждать, и это тоже вина/заслуга «неиспользуемых импортов». Понимание правильности такого решение могло прийти только с большим опытом.
    Согласен, что это непривычно, но это приводит к быстрой компиляции и чистому аккуратному коду в любом проекте на Go. И это бесценно. У программистов без опыта, конечно, приоритеты другие.

    Возмущение «в литералах есть запятые, а в группировке деклараций — нет = плохой дизайн языка» в комментарии, надеюсь, не нуждается.

    Причина №7. Кодогенерация в Go это просто костыль


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

    Меня эти доводы очень радуют, потому что показывают эту пропасть, между программистами-практиками и программистами-теоретиками.

    go generate отлично выполняет свою функцию, позволяя обходиться безо всяких Make-файлов даже тогда, когда вам нужно сгенерировать какой-то код с помощью сторонних утилит вроде yacc, thrift, protobuf или swig. Это простой, удобный и рабочий инструмент, который решает реальную задачу, практически ничего не добавляя в язык, кроме одной команды go generate и одного соглашения о формат комментария (что-то вроде hashbang). Это работает и работает хорошо.

    Но нет, для теоретиков это не важно. Теоретикам важно повесить нужный ярлык, и судить о вещах издалека, глядя на ярлыки.
    Далее автор мягко уходит в «мне лично кажется, что это плохо», но усиленное фамильярничание и надменность в адрес Пайка выдает искусственность такого «аргумента» о «плохом дизайне языка».

    Эпилог


    Go безусловно является языком строгим и упрямым — часто используют слово opinionated. У Go есть своё видение хороших и плохих практик, и он вас стимулирует следовать хорошим практикам и не дает следовать плохим. Хотите сотни неиспользуемых импортов в коде — ищите другой язык, хотите покрывать тестами код и смотреть степень покрытия — вот вам все карты в руки, хотите забивать на ошибки и прятать код обработки ошибок с глаз подальше — ищите другой язык, хотите стрелять себе в ногу с адресной арифметикой — туда же.
    Go — это ваш друг, более опытный и мудрый, который помогает вам делать более быстро более качественный код. Упрямый друг, у которого огромный опыт за плечами, и если вы захотите научиться у него — вы получите меньше проблем в будущем, больше свободного времени и больше удовольствия от работы. Но для этого нужно поверить ему, как другу, и понять, что long-term цели всегда важнее short-term хотелок.

    В отличии от многих других языков, Go рождался не студентами-любителями в порыве написать что-нибудь свое, и не теоретиками, гоняющимися за фишками из свежих научных трудов. Go есть результат колоссального опыта, отбора только проверенных временем концепций и очень глубокого понимания проблематики мира разработки ПО. И именно благодаря этому, он имеет такой элегантный дизайн, который позволяет ему такими темпами завоевывать датацентры и рабочие компьютеры программистов по всему миру.

    Статья же автора о том, что дизайн языка «плохой» — это, к сожалению, не более, чем попытка привлечь к себе внимание. В подростковом возрасте это нормально, но хочется донести автору, что искусственное разжигание хейтерства и холиваров никогда не бывает конструктивным. Подобными статьями, заведомо предвзятыми и не объективными, безусловно, автор наносит вред. К примеру, есть компании, где Go в процессе внедрения, и, зачастую, решение о том «писать несколько месяцев REST-бекенд на C++ и нанять для этого ещё 2 rock-star C++ программиста» или «перейти на Go и написать все быстро и качественно» принимает менеджер сверху, который может понимать области применимости языков, а может и не понимать. И достаточно такого вброса, чтобы человек, даже не читая и не вникая, решил для себя, что «Го не стоит использовать, раз такие статьи про него пишут». И это реальные ситуации.

    Ну а, к кому прислушиваться и с кого брать пример — каждый решает сам, конечно же.
    Метки:
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 355
    • +9
      согласен с автором добавлю отсебятины

      переход с одного языка на другой всегда требует время что, бы все улеглось в голове
      в случае с Го мне понадобилась пара недель, благодаря легкости и лаконичности языка

      а благодаря строгости компилятора и четкости инструкций на официальном сайте
      все пишут код более/менее в одном стиле, а это согласитесь многого стоит
      • +9
        Осмелюсь поблагодарить за статью! Действительно вчерашний пост (про «ужасный» язык) оставил в голове какое-то впечатление сумбура. Сейчас оно отступило :)
        • +1
          У меня оно еще не скоро пройдет ))
          Что касается golang, мне, как плавно переходящего с PHP, новый ЯП все больше начинает нравиться. Есть конечно же определенные нюансы, но это все равно большущий шаг вперед.

          P.S.: по части WEB, разумеется!
        • +2
          В комментариях к посту автора я попросил хотя бы одного человека привести три примера из своего реального кода, где ему нужно было бы вставлять элемент в середину массива — не написал никто
          В самом деле, лично я так в середину массива элементы не вставляю. Вот пример из реального проекта, где я вставляю элемент в серёдку (при этом рост этих массивов у меня ещё и спрогнозирован и их «capacity» равняется удвоенному прогнозу):

              // если вставка требуется по индексу, который больше
              // массива, просто добавляем в конец
              if i >= len((*arr)[org]) {
                  (*arr)[org] = append((*arr)[org], value)
              } else {
                  // надо добавить любой элемент в конец, чтобы появилось место
                  // если в срезе место есть, оно будет использовано автоматически
                  (*arr)[org] = append((*arr)[org], nil)
          
                  copy((*arr)[org][i+1:], (*arr)[org][i:])
                  (*arr)[org][i] = value
              }
          
          • 0
            Если можно без кода, я могу привести примеры:
            1. вставка строки в середину перечня товаров счёта;
            2. вставка строки в середину перечня ролей пользователя;
            3. вставка строки в середину перечня подзадач расписания;
            • 0
              Для таких штук существуют другие структуры данных: односвязный список, двухсвязный список, двунаправленная очередь.
              Но как с ними обстоят дела в go, в котором нет обобщений. Ведь с ними работа тоже получается неудобной.
              • +10
                Для таких штук существуют другие структуры данных: односвязный список, двухсвязный список, двунаправленная очередь.

                У этих «других штук» другие стоимости, что иногда может быть неудобно (Да, мне как-то была нужна упорядоченная структура с O(1)-доступом к произвольному элементу, и меня устраивало O(n) при ее расширении. Нет, кейс не помню, что-то из стандартных алгоритмов.)
                • –5
                  Так думать надо, а иногда и бенчмарки делать, если не очень очевидно, какая операция наиболее часто делается.
                  • +17
                    Ну вот подумали. Провели алгоритмический анализ. Подтвердили его бенчмарком. Вышло, что массив и вставки в середину — эффективнее всего для данного случая.

                    От этого в Go появится операция insert?
                    • –8
                      lair, ваши комментарии заполонили каждую статью про Go. Предлагаю вам сделать следующий шаг и написать реальный проект на Go. Отлично будет, если это будет open-source проект — тогда мы вместе посчитаем, сколько раз вам понадобился insert или обход слайса в обратном порядке. Все таки главное разногласие у вас с Go именно в том, что практично, а что нет.

                      Давайте, после многих месяцев и лет теоретизирования о том, почему Go плох, и насаживания своего мнения, перейдем к следующему этапу — к практике. Я знаю, это сложный шаг, но мы вас тут поддержим :)
                      • +5
                        У меня, к сожалению, нет реального проекта, который я мог бы без риска взять и перевести на Go.
                      • 0
                        В таком случае придется применить очень длинную строку

                        a = append(a[:pos], append([]T{x}, a[pos:]...)...)
                        

                        Возможно даже прокомментировать код для ясности, если опыта в go не хватает для понимания того, что там происходит, и забыть эту операцию на следующие несколько лет.
                        • –1
                          Угу. И так k раз.
                          • 0
                            С n-ного раза захочется узнать, а что же там написано, а если знаешь, то конструкция выглядит вполне обыденно. Но, впрочем, ничего не стоит завернуть это в функцию и использовать k раз.

                            ps
                            Надеюсь не появится как в прошлой теме комментатор, говорящий о великом множестве заранее неизвестных типов, для которых понадобится применять этот метод. Я понимаю, что если хочется придраться, то ничего не остановит, но с дуру можно и голову разбить. Надо уже как-то находить более реальные аргументы)
                            • 0
                              Надеюсь не появится как в прошлой теме комментатор, говорящий о великом множестве заранее неизвестных типов, для которых понадобится применять этот метод.

                              Вообще-то, я был одним из таких комментаторов.

                              И, к сожалению, это реальная жизнь.
                              • 0
                                Такова жизнь, но примеров из жизни никто так и не привел. Хотя мне еще тогда было интересно увидеть необходимость такой функции в серверном микросервисе на 100-200 строк, для создания которых и позиционирует себя golang.
                                • +3
                                  Не, если go позиционирует себя только для таких микросервисов, то ладно.
                                  • –2
                                    Ну там примеры из жизни были — «я хочу написать вот именно такую функцию именно таким способом».

                                    Ну а Golang себя не позиционирует, как язык для микросервисов — это, скорее, полезный побочный эффект, что маленькие сервисы писать удобно и легко и Go зачастую начинаются использовать в компаниях, с написания или переписывания отдельных сервисов. Как раз Go «позиционируется» для масштабов Google — большие кодовые базы, большие группы людей и т.д.
                                    • +1
                                      Вот и мы код с PHP на Go переписываем. Этот подход себя оправдывает. Сервисы показывают бОльшую производительность. Встроенная поддержка тестов позволяет делать код надежным и модифицируемым.
                                      И все это в продакшене с миллионами пользователей.
                                      Кто-то еще считает Go игрушкой, а кто-то уже сейчас получает от этого преимущество.
                                    • 0
                                      Из реальной жизни, безотносительно к операциям вставки и прочему, опыт показывает, что писать наиболее обобщённые сигнатуры функций полезно, потому что, во-первых, не привязываешься к деталям и, во-вторых, сразу видно, какие типы совпадают потому, что они должны совпадать (например, типы индексов начала и конца чего-либо в контейнере), а какие — случайно. Помогает избегать ошибок в реальной жизни, ага.
                                      • 0
                                        Здесь T это как-раз тип, перепутать не получится, не скомпилится
                                        Реальный код так будет выглядеть:

                                        a = append(a[:pos], append([]string{x}, a[pos:]...)...)
                                        
                                        • 0
                                          И мы снова возвращаемся к вопросу о том, как написать такую обобщённую функцию.
                                          • +1
                                            И мы снова возвращаемся к вопросу — Зачем?
                                            • –2
                                              Чтобы не привязываться к конкретным типам данных, внезапно.
                • –15
                  Go прекрасен!
                  Использую его уже более года, если что то и непонятно, то нужно лишь немного терпения (и умения читать, конечно) что бы разобраться!
                  • –16
                    В любом случае, не стоит недооценивать труд столь большой компании.
                    • +57
                      Вот я прочитал обе статьи и… немного не понял.
                      Вы так описали, что у меня сложилось довольно отрицательное впечатление о самом языке, причем именно от вашей статьи.
                      Половина аргументов выглядит «так делать нельзя, потому что так делать плохо.»
                      А вот если нужно, то пиши свой костыль и страдай.

                      Вы очень много пишите про дизайн Go и про то, что он такой удобный, но… на самом деле это нет.
                      Строгий язык не может быть удобным.
                      А язык, в основе которого лежат какие-то фиксированные практики программирования, которые говорят что «делать можно только так» тем более не может быть удобным.

                      Например, почему нужно писать так:
                      numbers = append(numbers[:2], append([]int{3}, numbers[2:]...)...)
                      

                      Вместо того, что бы писать так:
                      numbers = append(numbers[:2], 3, numbers[2:]...)
                      

                      Чем можно обосновать такое решение?

                      Или заменить int[]{3} на просто [3].

                      • +35
                        Присоединяюсь к мнению SirEdvin. Если статья «Почему Go это плохо продуманный язык программирования», воспринимается как «что мне не нравиться в Go, а нравиться в других языках».

                        То статья «Почему Go это хорошо продуманный язык программирования», воспринимается скорее как «Почему Go это хорошо продуманный плохой язык программирования»
                        • –12
                          Статья «Почему Go это плохо продуманный язык программирования» воспринимается как должна — молодежь тренируется писать статьи, выискивая противоречивые темы и не слишком основательно прорабатывает аргументацию, смещая акцент в эмоции. «Инженерный» троллинг :)

                          А вторая — попытка восстановить баланс разумного доброго и вечного. Сам бы такую написал, но что-то ленивый последнее время стал.
                          • +20
                            попытка восстановить баланс разумного доброго и вечного

                            Серьезно?
                            Любой, кто писал на С/C++, знает во что превращаются проекты, после того, как кодом поработают 5-10 программистов, и код пройдет несколько стадий рефакторинга

                            писать несколько месяцев REST-бекенд на C++ и нанять для этого ещё 2 rock-star C++ программиста

                            и в Go, в отличие от, скажем С++, нет undefined behavior при сокрытии переменных

                            Все эти сравнения ( причем первые два — субъективные ) С++ с Go происходят, когда есть возможность показать, что Go лучше. При обратном сравнении приводится такая аргументация
                            Go — это другой язык, это не C++

                            И как финальный аккорд — проезд по остальным языкам
                            В отличии от многих других языков, Go рождался не студентами-любителями в порыве написать что-нибудь свое, и не теоретиками, гоняющимися за фишками из свежих научных трудов

                            Я бы Вашу характеристику отнес бы к обеим статьям
                            не слишком основательно прорабатывает аргументацию, смещая акцент в эмоции. «Инженерный» троллинг :)
                            • +10
                              Все эти сравнения ( причем первые два — субъективные ) С++ с Go происходят, когда есть возможность показать, что Go лучше.

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

                              Простите за резкость ещё раз, я всё ещё под впечатлением от рекомендации автором статьи использования связного списка для реализации сортированных массивов. В соседнем треде, да.
                              • –1
                                я всё ещё под впечатлением от рекомендации автором статьи использования связного списка для реализации сортированных массивов.

                                Добавление элемента в сортированный список.
                                Вы самостоятельно изменили слово «список» на «массив», и находитесь в шоке. Почему бы и другие слова не поменять, как вам хочется?
                                Ни о чём.
                                • 0
                                  Приведите три реальных примера, когда Вам нужно засовывать элементы в произвольное место в массиве/слайсе.

                                  Это ваша цитата.

                                  Там вам товарищ, правда, вот ответил почему-то со словом «список», ну да ладно. Там как раз понятно, что раз он отвечал про массив, то массив ввиду и имелся.
                                  • –6
                                    Я попросил три реальных примера (показать код, к примеру или рассказать суть задачи).
                                    Человек привел надуманный пример и сказал одно (сортированный список).
                                    Вы перекрутили его слова, обвинив меня в том, что я предлагаю список для реализации сортированного массива.
                                    Потом сказали, что «там как раз понятно».

                                    Новый формат общения на Хабре, мда.
                                    • +2
                                      Да что ж такое…
                                      Ну как мне поддерживать сортированный массив на Go, а?
                                      • +1
                                        сделайте тип, опишите правила сортировки, логику резервирования памяти, возможно вы будете не целый массив выделять, а например блоками для оптимизации операций вставки.
                                        как мне поддерживать сортированной массив на C?
                                        • 0
                                          А правила сортировки — они относятся к типу или к месту вызова?
                                          А блоки — это уже не массив, а deque.
                                          А почему на C, а не на C++?
                                          • 0
                                            Мало того, что вы мне вопросом на вопрос ответили. Так ещё и вопросы какие-то странные.
                                            Ок, на C не получилось, давайте на C++
                                            • 0
                                              v.insert(upper_bound(v.begin(), v.end(), x), x);
                                              

                                              — выполняет двоичный поиск и вставляет элемент.
                                              • +1
                                                Вопросы не странные.

                                                Операция сравнения должна задаваться в момент определения типа или в момент вызова функции сортировки/поиска?
                                                Условно, если у меня есть структура, описывающая человека, с двумя полями — имя и фамилия, то мне надо иметь отдельно по типу на структуру, сравниваемую по имени, отдельно по фамилии, отдельно по их комбинации, и так далее? Или компаратор должен задаваться в момент вызова sort/upper_bound/etc?
                                                В плюсах доступны оба варианта, если что.

                                                А код на C++ уже за меня написали. Потребуется кастомный компаратор, можно будет написать
                                                v.insert(std::upper_bound(v.begin(), v.end(), x,
                                                            [](const auto& left, const auto& right) { return left.field < right.field; }),
                                                        x);
                                                
                                                • 0
                                                  конкретно я про это:
                                                  > А почему на C, а не на C++?
                                                  я то конечно и попросил C т.к. там нет дженериков. В целом не сказать что приходилось прям сильно страдать от этого в Go (как-то либо стандартный sort, либо штуки на interface{}, либо совсем кастом) но реально они должны быть здесь (хотя бы для стандартных контейнеров).
                                                  кстати ваши примеры на 11 плюсах, которые через 20 лет вышли после первой версии
                                                  • +1
                                                    я то конечно и попросил C т.к. там нет дженериков.

                                                    А Go позиционируется как альтернатива C? Это что-то новенькое!

                                                    Давайте с ассемблером сравним, будет вообще по всем пунктам в выигрышном свете.

                                                    кстати ваши примеры на 11 плюсах, которые через 20 лет вышли после первой версии

                                                    И что это нам говорит?

                                                    Кстати, конкретно этот пример на 14-х плюсах, ну да ладно, простой заменой auto на конкретный тип сводится к 11-м.
                                                    • 0
                                                      C как бы это что-то старенькое.
                                                      Вообще это все ЯП, c++/c, go, python, haskell, php и т.п. и они все друг другу альтернативы.
                                                      > И что это нам говорит?
                                                      Нам это говорит что все развивается, где-то быстрее, где-то медленнее
                                                      > Кстати, конкретно этот пример на 14-х плюсах
                                                      в 11 добавили авто но не дописали что его можно использовать в лямбдах?

                                                      Ну а по сути я не очень понимаю, что мы тут выясняем, вы где-то увидели в офф. сайтах что Go что-то там заменяет? Вас задевает само его существование или как?
                                                      ЯП они на то и разные чтобы был выбор. Под задачи, под условия и т.п.

                                                      В плюсах нет встроенного параллелизма, сборщика мусора, а широкие возможности ООП по наследованию, виртуальным функциям и т.п. зачастую очень не плохо бьют по производительности.
                                                      И что мне теперь ржать в голос и говорить, что плюсы отстой?
                                                      Или вместо того чтобы сделать рабочий сервис за час, я буду сутки писать и дебажить его на плюсах лишь по тому что я не могу забабахать десяток шаблонных классов?
                                                      • +2
                                                        Вообще это все ЯП, c++/c, go, python, haskell, php и т.п. и они все друг другу альтернативы.

                                                        PHP — это альтернатива хаскелю и C++, ок.

                                                        Нам это говорит что все развивается, где-то быстрее, где-то медленнее

                                                        Но сам язык Go же развиваться не будет никогда. Разве это не утверждается его создателями? Мол, язык идеален, всё.

                                                        в 11 добавили авто но не дописали что его можно использовать в лямбдах?

                                                        Потому что auto в аргументе лямбды — это совсем не то же самое, что auto в объявлении переменной. Это даже называется специальным словом, generic lambdas, и разворачивается в структуру с шаблонным operator().

                                                        Ну а по сути я не очень понимаю, что мы тут выясняем, вы где-то увидели в офф. сайтах что Go что-то там заменяет? Вас задевает само его существование или как?

                                                        Подумайте на досуге, почему вы спросили о сравнении с C, а не с ассемблером или Brainfuck или Whitespace.

                                                        В плюсах нет встроенного параллелизма

                                                        Есть (хотя кривой, не кривой делается на boost.asio один раз и почти на всю жизнь).

                                                        сборщика мусора

                                                        И GUI-библиотеки в самом языке нет.

                                                        а широкие возможности ООП по наследованию, виртуальным функциям и т.п. зачастую очень не плохо бьют по производительности

                                                        Например? И что такое «очень неплохо»?

                                                        Или вместо того чтобы сделать рабочий сервис за час, я буду сутки писать и дебажить его на плюсах

                                                        Там сутки подебажите, тут сутки подебажите, а потом будете делать сервисы за полчаса, как C++ освоите. Да, у плюсов кривая обучения круче, но в результате вы овладеваете существенно более мощным инструментом.
                                                        • 0
                                                          > PHP — это альтернатива хаскелю и C++, ок.
                                                          Я вам написал подробнейшим образом, а вы не прониклись, да альтернатива, зависит от задачи.
                                                          Если вам нужно сделать сайт из пары страниц, не надо упираться и делать его на плюсах.

                                                          > Но сам язык Go же развиваться не будет никогда. Разве это не утверждается его создателями?
                                                          Пруфы? А вообще как вы сами думаете, что вероятнее приписывание выдуманных слов абстрактным авторам или то что один из создателей языка решил его зарыть?

                                                          > Подумайте на досуге, почему вы спросили о сравнении с C, а не с ассемблером или Brainfuck или Whitespace.
                                                          Потому что я сам пишу на C и там нет generics. Подумайте на досуге, почему вы не смогли написать этот код.

                                                          > Есть (хотя кривой, не кривой делается на boost.asio один раз и почти на всю жизнь).

                                                          go func () {
                                                          // do
                                                          }()

                                                          подобная есть? кстати такую конструкцию я использую гораздо чаще, чем сортировку массивов

                                                          и ок, в Go есть дженерики, правда кривые, хотя например то что это потом лежит кодом (ага и тестами. тоже генеренными) можно даже в плюс записать

                                                          > И GUI-библиотеки в самом языке нет.
                                                          опять сравнили теплое с пальцем.

                                                          > Там сутки подебажите, тут сутки подебажите, а потом будете делать сервисы за полчаса, как C++ освоите.
                                                          Дело не в освоении, в зависимости от положения на кривой меняется лишь процент ошибок, но люди их все равно делают в не зависимости от уровня компетенции.

                                                          В общем ваша позиция плюсы для всего, моя — надо выбирать правильные инструменты (из задачи из возможностей бизнеса и т.п.), мне нечего вам доказывать, а мне вы не докажите, поэтому предлагаю остаться при своих
                                                          • +1
                                                            Я вам написал подробнейшим образом, а вы не прониклись, да альтернатива, зависит от задачи.

                                                            В какой области PHP является альтернативой C++? Ну, чтобы задача более-менее распространённо решалась и на плюсах, и на PHP.

                                                            Пруфы?

                                                            Сложилось такое впечатление от местных go-пологетов. Что язык идеально спроектирован, ничего нового добавлять не нужно, не вписывается в философию, и так далее.

                                                            А вообще как вы сами думаете, что вероятнее приписывание выдуманных слов абстрактным авторам или то что один из создателей языка решил его зарыть?

                                                            Этот пассаж я, признаться, не понял.

                                                            Потому что я сам пишу на C и там нет generics. Подумайте на досуге, почему вы не смогли написать этот код.

                                                            А ещё вы этот код не сможете написать на Brainfuck или Whitespace. И что теперь?

                                                            подобная есть?

                                                            Один раз за всю жизнь (или за проект, ок) сделали тредпул, и всё,
                                                            как пример.

                                                            Впрочем, можно и без тредпулов, std::thread практически так же будет выглядеть (хотя это, конечно, не зелёные треды).

                                                            хотя например то что это потом лежит кодом (ага и тестами. тоже генеренными) можно даже в плюс записать

                                                            Не понимаю, как у вас это записывается в плюс.

                                                            опять сравнили теплое с пальцем.

                                                            А почему тёплое с пальцем, а не тёплое с тёплым или палец с пальцем?

                                                            Дело не в освоении, в зависимости от положения на кривой меняется лишь процент ошибок, но люди их все равно делают в не зависимости от уровня компетенции.

                                                            Да, если вы делаете 0.0005% ошибок, условно (или как вы там проценты измеряете), то этим можно пренебречь.

                                                            В общем ваша позиция плюсы для всего

                                                            Нет, не такая. Я кроме плюсов могу потыкать в R для подсчета всяких статистик по данным, в Haskell для много чего, в Bash, если надо что-то быстренько заскриптовать на 10 строк. А вот зачем мне Go, я не очень понимаю.
                                                            Более того, как в итоге позиционируется Go, я вообще не понимаю. Если это язык для микросервисов в 2015 году, то сравнивать его с C, как вы это делаете, несколько странно.
                                                    • 0
                                                      Нет, мой пример на C++98, самом первом стандарте.
                            • +1
                              Вы точно прочитали статью? Где в ней про удобство?

                              Написано, что Go помогает писать код с которым будет меньше проблем в будущем.
                              • +6
                                который помогает вам делать более быстро более качественный код

                                перейти на Go и написать все быстро и качественно

                                Возможно, я ошибаюсь, но мне кажется, что на неудобном языке быстро не напишешь.
                                Поэтому удобство подразумевается в данном контексте.
                                • 0
                                  Раз пишется быстро то есть подозрение что все же достаточно удобен. Конечно же это не значит абсолютное удобство для всех и для любых задач.
                                  • +1
                                    На Basic тоже что-то пишется…
                                  • 0
                                    Как-то странно. Привели пример НЕКОТОРЫХ!!! нестыковок в языке по сравнению с другими языками, подчеркиваю — с другими. И внезапно язык становится неудобным во всем. Я когда выбирал профессию программиста, честно, не думал, что здесь в итоге будет царствовать вкусовщина и такая податливость хайпам. Современному языку программирования на ранних этапах важно одно: чтобы его пропиарило как можно больше значимого в узком круге народа. Если бы все случилось чуть иначе, и, скажем, Rust вышел чуть позже, а о Go положительно отозвалось бы чуть больше народа, взгляды были бы совсем другими. Некоторая неуклюжесть работы со срезами показалась бы незначительной, зато каждый, кто выбрал бы этот язык тешил бы себя мыслью о причастности к чему-то вечному и великому только благодаря своему выбору. Я не преувеличу, если скажу, что немного разочарован в сообществе программистов. Более того, все эти кровавые холивары происходят по той же самой причине. Просто одни адепты выбрали маоизм от программирования, другие выбрали условный капитализм. Перед их носами махнули красной тряпкой в виде не совсем, надо признать, честной статьи, и они готовы грызть друг другу глотки в интернетах. По сути, плевать мне хотелось, если кто-то будет писать на брейнфаке свои проекты. Ну честное слово, я знаю, чего хочу от жизни — ну наздоровье. Зачем мне переубеждать человека, и тем более портить ему карму — да еще так остервенело. Но все меняется, когда язык становится идеологией. Вот тогда да, тогда тот, кто не с нами — тот непременно враг, тот достоин всяческого унижения и обструкции. Да на костре сжечь еретика, он слайсами манипулирует кодом, на строчку больше, чем мы. Распять мерзавца, как он посмел высказать свое мнение! Четвертовать его!
                                    • 0
                                      Вы почему-то написали это в ответ на мой комментарий, так что отвечу.
                                      1.
                                      Распять мерзавца, как он посмел высказать свое мнение! Четвертовать его!

                                      Лично Вам я поставил плюс.
                                      2.
                                      И внезапно язык становится неудобным во всем

                                      Я этого не говорил. Прочитайте сообщение SirEdvin. В нем он спрашивает, почему некоторые моменты языка неудобны, чем вызваны данные решения создателей языка. Ему в ответ overmes пишет, что удобство языка нигде в статье не упоминается. И я отвечаю, что оно подразумевается во многих местах данной статьи.
                                      3.
                                      Я не преувеличу, если скажу, что немного разочарован в сообществе программистов. Более того, все эти кровавые холивары происходят по той же самой причине.

                                      А мне кажется, что это как раз двигатель развития — аргументированный спор ( не путать с тупым флеймом! ). Программисты в душе — идеалисты. Хочется найти священный Грааль лаконичности, понятности и производительности. Вот и происходят споры, выявляющие плюсы и минусы каждого инструмента. Главное — не скатываться на личности и эмоции.
                                      • +5
                                        Вы считаете, что ищете святой Грааль. А я вижу, как большинство останавливает свой выбор на чем-то, что нравится именно им, и начинает верить, что это — святой Грааль для всех. В этом-то и проблема.
                                  • +19
                                    > Написано, что Go помогает писать код с которым будет меньше проблем в будущем.
                                    Это из области метеорологических прогнозов. Поживем — увидим. Предыдущим стремительно завоевывавшим рынок языком, с которым не будет проблем в будущем был КОБОЛ.

                                    А вот почему я должен ради мифического удобства в будущем сейчас страдать от неудобства синтаксиса — вопрос, оставшийся без ответа. Да и как удобный синтаксис может мне вдруг навредить завтра — тоже не очень ясно.

                                    • 0
                                      > Да и как удобный синтаксис может мне вдруг навредить завтра — тоже не очень ясно.
                                      В общих чертах-то ясно. Плохой код должен выглядеть плохо. То есть идея в том, что глядя на вставку в середину массива, человек должен заподозрить неладное и убедиться, что оно к месту. Скажу за хаскель. Если бы писать там с мутабельными переменными было так же удобно, как без них, хаскель был бы другим. Вопрос только в том, что именно счесть плохим кодом, и вот тут да, мнения разнятся. Время покажет.
                                      • +6
                                        В хаскеле это математически обосновано и следует из базовых свойств языка и абстракций (запихивать всё в unescapable-монаду ST, например). А тут — набор ad-hoc-костылей и решений с потолка, уж простите.
                                        • –3
                                          А тут — набор ad-hoc-костылей и решений с потолка, уж простите.

                                          Это не так. Хотите себя убеждать, что Go — это набор костылей с плохим дизайном, пожалуйста. Самообман — дело легкое.
                                          • +4
                                            Мне каждется, доказать то, что это обман достаточно просто, для этого все лишь нужно указать ссылки на статьи. Если язык не базируется на статьях, то можно попытаться агрументировать тем, что это хороший инженерный язык, и привести в доказательства рассылки и статьи в блог постах авторов, объясняющие решения, обосновывая это технически. К сожалению это будет доказательстов того, что язык построен на ad-hoc решениях (ну или костылях, смотря какая агрументация).
                                        • –3
                                          То есть идея в том, что глядя на вставку в середину массива, человек должен заподозрить неладное и убедиться, что оно к месту.

                                          Именно так. Спасибо, хоть кто-то написал, что понимает о чем речь.
                                          Это и вправду такая сложная концепция для понимания или я её непонятно объясняю?
                                          • +7
                                            Мне сложно сказать, потому что я понимал, о чем речь, до ваших объяснений, но, как мне кажется, основная претензия не к самому подходу «плохое должно выглядеть плохо», а к конкретному выбору того, что считать плохим. Ни в C++, ни в Хаскеле, ни много где ещё нет проблемы написать вставку в середину массива, т.е. если уж сильно надо, можно написать красиво. Это приводит реально к каким-то серьёзным проблемам? Если да, то было бы замечательно увидеть примеры и какую-либо статистику, а так это звучит несколько безапелляционно. Ну т.е. проблема в подаче и восприятии. Если подать как «авторы [языка] считают, что это решение оправдано», то это одно, а если «это будет хорошо в long term» без внятного ответа на вопрос «почему», то в купе с холиварным несколько стилем это и приводит к соответствующему стилю обсуждения.
                                            • +12
                                              Программисты на Го настолько тупы, что им нужно синтаксисом намекать на то, что вставка в середину массива — дорогостоящая операция.

                                              Спасибо, теперь все встало на свои места.

                                      • +3
                                        Так «нужно» писать, потому что так писать не нужно. Если использовать неправильный инструмент, результат получается некрасивым (мягко говоря).

                                        Вставлять элемент в середину слайса таким образом как минимум не оптимально. Дело в том, что append может копировать массив, на котором основан слайс, если памяти не хватает. В данном примере копирование может быть осуществлено два раза.

                                        Правильно — увеличить размер слайса и сдвинуть все элементы на нужный offset и установить новый элемент (или несколько элементов):

                                        s = append(s, 0)
                                        copy(s[i+1:], s[i:])
                                        s[i] = x
                                        
                                        • 0
                                          То есть, если мне нужно собрать в один массив несколько массивов и чисел мне тоже нужно будет так делать?

                                          А как же синтаксический сахар?
                                          • 0
                                            Много сладкого вредно для здоровья :)

                                            Если вам нужно собрать в один массив несколько массивов и чисел — вы сами решайте как вам это нужно сделать, в каком порядке и т.д. К вашим услугам append, make, и copy — вполне лаконичные и простые операции. Понять потом код очень просто.
                                            • +1
                                              Просто я не знаю Go, но разбираюсь по статье.
                                              Я могу написать что-то похожее на:
                                              append(arr1,1,arr2,3,arr4,5)
                                              

                                              ?
                                              • 0
                                                Нельзя, к сожалению. У append только одна реализация, которая проверяет тип при вставке.

                                                Думаю, что корректная реализация в случае статической типизации будет довольно громоздкой.

                                                Как то append<T'>(slice []T', e []T'|T'...) — сложновато…
                                                • 0
                                                  Почему «к сожалению»? Сейчас append — детерминированная функция, которая делает одну ясную и четкую операцию.
                                                  Если вам нужно добавить несколько других значений и слайсов — сделайте это явно. Избавляйтесь от этого желания «написать все в два символа», чтобы потом другие программисты гадали, что же имелось ввиду и зачем.
                                                  • +1
                                                    То, что сложно для компилятора, не всегда сложно для человека. Смысл выражения append(arr1,1,arr2,3,arr4,5) вполне очевиден, особенно если функцию назвать join, а не append
                                        • 0
                                          А лучше так:

                                          numbers = numbers[0..2] ~ 0 ~ numbers[2..$];
                                          • +1
                                            Тут уже спорный вопрос.
                                            Я не уверен, что пойму, что делать операция ~, если увижу ее в незнакомом языке.
                                            Тут же вроде за простоту сражаются.
                                            • –1
                                              Это конкатенация. Слово «append» тоже не говорит, что это соединение массивов, а не, например, добавление записей в файл :-)
                                          • +1
                                            Строгий язык не может быть удобным.

                                            Конечно. Равно как и хорошим.
                                            А если серьезно — язык должен быть удобным не для написания кода, а в первую очередь для его сопровождения. И тут строгость Go на вашей стороне. Потому что поддерживать код на Go — УДОБНО.
                                            Правда я так и не увидел аргументов (т.е. конкретных примеров) как строгость делает язык неудобным. Следуя такой логике можно дойти до того, что JavaScript/PHP очень удобные языки. Удобнее Питона и тем более Java/C#. Но я бы не согласился с такими утверждениями.
                                            • 0
                                              Правда я так и не увидел аргументов (т.е. конкретных примеров) как строгость делает язык неудобным.

                                              Все дело в ограничениях, которые накладывает на вас язык.
                                              Подуймайте, какой костыль нужно будет соорудить, что бы написать, например, удобные матрицы на языке Go для различных типов данных. Сколько раз вам нужно будет просто копировать туда-сюда код? А теперь представьте, что вы еще добавили изменение в один тип матрицы, и вам нужно перенести их в другие…
                                              Вы считаете, это удобно?
                                              Следуя такой логике можно дойти до того, что JavaScript/PHP очень удобные языки. Удобнее Питона и тем более Java/C#. Но я бы не согласился с такими утверждениями.

                                              Внезапно, но вроде как именно этот пункт выставляется одним из основных преимуществ Node.js для новичков.
                                              Потому что писать различные веб-приложение на JavaScript или Python (серверную часть) куда проще и удобнее, а следовательно и быстрее, чем на Java/C#.
                                              язык должен быть удобным не для написания кода, а в первую очередь для его сопровождения.

                                              Это сложный дисскусионный вопрос. Что лучше, потратить больше времени на написание самого кода или на его review и комментирование?
                                              • +2
                                                А вы про какую строгость говорите?
                                                • 0
                                                  Вроде как о наличии различных синтаксических соли и сахара.
                                                • 0
                                                  То, что в языке нет generics — я тоже не считаю плюсом. Но это ничего не говорит про дизайн языка. Есть множество языков, где их нет, во многих они появились не сразу. Вполне возможно, что и в Go 2.0 (например) они таки будут.

                                                  Внезапно, но вроде как именно этот пункт выставляется одним из основных преимуществ Node.js для новичков.

                                                  О чем я и говорю — для новичков, а не для серьезной разработки. Впрочем кем это выставляеnся — не ясно. Go — простой язык, и для новичка изучить его по силам.

                                                  проще и удобнее, а следовательно и быстрее

                                                  Быстрее «наговнокодить» имелось в виду? :)

                                                  Сопровождение — это не review и комментирование, а debugging и внесение серьезных изменений в приложение. А эти моменты — часто отнимают куда больше времени, нежели «первичное» написание кода.
                                                  И да — писать на Go быстро. Не так быстро как на Питоне, но сравнимо с Java/C# и быстрее, чем на C++.
                                                  • 0
                                                    То, что в языке нет generics — я тоже не считаю плюсом.

                                                    Как там фраза про «Язык уже закончен и развиваться не будет»?
                                                    Сопровождение — это не review и комментирование, а debugging и внесение серьезных изменений в приложение. А эти моменты — часто отнимают куда больше времени, нежели «первичное» написание кода.

                                                    Если проект был нормально спроектирован и code review проводилось с целью поддерживать эту архитектуру, то проблем не будет. Аналогично, если написать плохую архитектуру на Go, с ней будут такие же проблемы.

                                                    С другой стороны, возможно, Go позволяет следить за архитектурой проще, чем другие языки. Но тут опять же встает вопрос выбора приоритетов.
                                                    • 0
                                                      Если проект был нормально спроектирован

                                                      Вот так никогда в реальности не бывает.
                                                      Если вы действительно заранее сели и на пару лет вперед хорошо продумали Архитектуру, то это значит только, что вы проели огромное денег бизнеса, впустую.
                                                      Архитектура — это то, что выстраивается в результате развития проекта. И она меняется и должна меняться. И вот эти изменения должны быть максимально простыми. Чего Go с успехом и добивается. А то, что в середину слайса вставить значение «не красиво выглядит» — в реальности на это всем плевать.
                                            • +25
                                              Так-так, что тут у нас сегодня? Ничего нового, в Go одни правильные решения, все пытаются делать из него питон и совать свои закоренелые паттерны. Ну, что я могу сказать? Хорошо.
                                              • +23
                                                По большей части я согласен скорее с вами, чем с автором оригинальной статьи. Кроме одного пункта — пункта 7.
                                                Комментарии по определению это такие пометки, присутствие или отсутствие которых в коде не меняет поведения кода. Так во всех языках. Ну, разве что в Python встречаются любители хранить метаданные в docstring'ах, но их даже коллеги за это колотят. А тут вы говорите, что вызывать из комментариев кодогенератор — это норма. Кодогенератор, Карл! Да даже в C++ максросы сделаны лучше. А что, если этот комментарий сольётся с комментарием к функции ниже? В общем, можно сколько угодно защищать такое решение, ссылаясь на авторитет Пайка, но это реально выглядит на решение из разряда «да ну, для одного кейса не будем прагмы добавлять, сделаем магический комент и так сойдёт»
                                                • –3
                                                  это машиночитаемый комментарий он автоматом ничего не вызывает, для него существует отдельная команда, которую надо запускать руками.
                                                  по смыслу — стандартизовали то, что уже использовали люди, только они это писали в make файлах или так же в комментариях: https://github.com/golang/net/blob/master/html/atom/gen.go.
                                                  Это чтобы например на основе описания protobuf сгенерировать исходный код на go и т.п.
                                                  • +21
                                                    Стандартизировать костыли — божественный подход к дизайну
                                                    • –2
                                                      эм, то есть автоматическая генерация кода в любой форме, это костыль?
                                                      вы уж определитесь к чему претензии к тому, что стандартизовали или как это сделали.

                                                      ну и в тему про магические комментарии:
                                                      https://github.com/golang/go/blob/master/src/runtime/wbfat.go#L6
                                                      https://github.com/golang/go/blob/master/src/runtime/wbfat_gen.go#L5
                                                      • 0
                                                        А тут изобретены аннотации, но почему-то не выделены явно синтаксически.
                                                        • +10
                                                          Магические комментарии — это костыль. Претензии к тому, КАК сделали.
                                                          • –2
                                                            магические комментарии — это суть есть аннотации, как один из вариантов размещения неких метаданных в коде, чем "@NotNull" принципиально отличается от //go:nosplit или //go:generate?
                                                            • +7
                                                              Тем, что он
                                                              — не выглядит как комментарий
                                                              — обрабатывается не как комментарий

                                                              Аннотация явно говорит «тут делаются разные дела»
                                                              В случае комментария может быть так:

                                                              //go:generate toolname -params -blabla
                                                              //Hey! Look at my awesome function Blabla
                                                              //Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                                                              //Donec tortor erat, rhoncus ac turpis id, ullamcorper congue odio
                                                              func Blabla() {
                                                                  // code...
                                                              }
                                                              
                                                              • 0
                                                                вас смущает, что go doc зацепит этот комментарий к функции Blabla?
                                                                • 0
                                                                  Меня, кстати, смущает.

                                                                  (скажем, в C# просто комментарии и документационные комментарии отличаются)
                                                                  • 0
                                                                    не писал на c#, не могу сходу представить что вы имеете ввиду
                                                                    • +1
                                                                      public class SomeClass
                                                                      {
                                                                        ///<summary>Это пойдет в документацию</summary>
                                                                        ///<remarks>И это пойдет в документацию</remarks>
                                                                        ///<param name="f">f-word</param>
                                                                        ///<returns>a swear based on <paramref name="f"/></returns>
                                                                        //а тут программист может писать что угодно, это не войдет ни в какую документацию
                                                                        public bool WhatThe(string f)
                                                                        {
                                                                        }
                                                                      }
                                                                      


                                                                      Естественно, все это поддерживается IDE и на уровне автодополнений, и на уровне показа подсказок при наведении на использование.
                                                                      • +1
                                                                        Там есть вот такой комментарий
                                                                        //Это комментарий
                                                                        

                                                                        а есть вот такой
                                                                        ///Эта функция считает синусы
                                                                        


                                                                        из комментариев второго типа генерируется документация, из комментариев первого — нет
                                                                        • 0
                                                                          аналог на go:
                                                                          // это просто коммент

                                                                          // а это информация о работе функции, она пойдет в godoc
                                                                          func DoCool() {
                                                                          }
                                                                          • 0
                                                                            В вашем же примере github.com/golang/go/blob/master/src/runtime/wbfat.go#L6
                                                                            //go:nosplit пойдёт в godoc
                                                                            Это норма, да?
                                                                            • +1
                                                                              он не пойдет в godoc — это приватная функция
                                                                              • 0
                                                                                Если я не ошибаюсь дока должна еще начинаться с названия метода?

                                                                                // это просто коммент
                                                                                
                                                                                // DoCool а это информация о работе функции, она пойдет в godoc
                                                                                func DoCool() {
                                                                                }
                                                                                
                                                                              • +2
                                                                                Это не норма. nosplit и noescape — это внутренности компилятора и рантайма, в реальном коде вы ничего подобного не пользуете. //go:generate, если уж понадобилось, вы пишете единожды в заголовке файла, а не где попало. Обсуждаемая выше проблема — чистой воды теоретизирование.
                                                                                • +2
                                                                                  Обсуждаемая выше проблема — чистой воды теоретизирование

                                                                                  Как будто это делает решение поместить в комментарии инструкции для кодогенератора или «внутренности компилятора и рантайма» long-term хорошим решением.
                                                                                  • 0
                                                                                    А что, по вашему, будет хорошим решением?
                                                                                    • +3
                                                                                      Выделить это в отдельные сущности, как это было сделано во всех других языках?
                                                                                      Например, в аннотации.
                                                                                      • –4
                                                                                        Я, к примеру, не вижу плюсов от «введения новой сущности», зато ломается совместимость. Плодить новую сущность на каждый чих — это именно то, чем Go не является. Если хочется такого, то лучше выбирать другие языки. Если всё таки есть реальные проблемы с go generate или с комментариями — велкам в коммьюнити, выслушают, напишете пропозал, и ваше решение, раз оно реально лучше — имплементируют. Всё просто.
                                                                                        • +2
                                                                                          Я не знаю, как вы умудряетесь новой сущностью ломать совместимость, наверное вы избранный. Обычно она ломается, когда происходит наоборот.

                                                                                          Реальная проблема с комментариями это то, что в они не комментарии, а метаданные. В которых можно выполнять произвольные команды, делать сишные вставки и заниматься прочим бредом.

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

                                                                                          А это плохо.
                                                                                          • –3
                                                                                            Я не знаю, как вы умудряетесь новой сущностью ломать совместимость, наверное вы избранный.

                                                                                            Раз избранный, то поясню — новая сущность в Go 1.5 == ошибка компиляции в Go 1.4.
                                                                                            Не за что.

                                                                                            А это плохо.

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

                                                                                            • +3
                                                                                              Раз избранный, то поясню — новая сущность в Go 1.5 == ошибка компиляции в Go 1.4.

                                                                                              Эмм, а в Go правда считается нормальным компилировать код для поздних версий ранними компиляторами?
                                                                                              • +3
                                                                                                Раз избранный, то поясню — новая сущность в Go 1.5 == ошибка компиляции в Go 1.4.

                                                                                                Очень смешно звучит. То есть Go 1.5 совсем не добавляет ничего нового в сравнении с Go 1.4? Я вас правильно понял?

                                                                                                Главное навесить ярлык. Ясно, спасибо.

                                                                                                Главное думать головой.
                                                                                                Когда я пишу комментарий, это должен быть комментарий. Он не должен влиять на работу программы. Это не должна быть инструкция для препроцессинга, Си-шная вставка или еще что-то, что придет в голову создателю языка.

                                                                                                Лишить язык программирования возможности писать комментарии — это плохое решение.
                                                                                                • –3
                                                                                                  То есть Go 1.5 совсем не добавляет ничего нового в сравнении с Go 1.4? Я вас правильно понял?

                                                                                                  Нет, прямая совместимость не гарантируется, но при обсуждении различных дизайнов, там где можно её не ломать, лучше не ломать. Так поняли?

                                                                                                  это должен быть комментарий
                                                                                                  Он не должен
                                                                                                  Это не должна быть инструкция для препроцессинга… или еще что-то, что придет в голову создателю языка.

                                                                                                  Не очень понимаю, почему язык должен вам что-то, что пришло лично вам в голову, а не создателям языка. Может объясните, чем ваше мнение тут весомей?

                                                                                                  Лишить язык программирования возможности писать комментарии — это плохое решение.

                                                                                                  Согласен. Только непонятно, про какой вы язык говорите.
                                                                                                  • +6
                                                                                                    Нет, прямая совместимость не гарантируется, но при обсуждении различных дизайнов, там где можно её не ломать, лучше не ломать. Так поняли?

                                                                                                    Нет. Если совместимости все равно нет, тогда зачем вы к ней аппелируете?

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

                                                                                                    Я говорил про комментарий. То, что он должен исходит из его определение.

                                                                                                    Согласен. Только непонятно, про какой вы язык говорите.

                                                                                                    Про Go, в котором комментарии были заменены на метаданные.
                                                                                                    • –2
                                                                                                      Нет. Если совместимости все равно нет, тогда зачем вы к ней аппелируете?

                                                                                                      Я к ней аппелирую, потому что это один из моментов, по которым принимаются решения. Уже писал, что дизайн языка — это не черное и белое, и не бинарный выбор «очевидно, что это должно быть так» и «не так». Неужели это и вправду нужно разъяснять 15 комментариев подряд?

                                                                                                      Я говорил про комментарий. То, что он должен исходит из его определение.

                                                                                                      По определению самолёт — должен летать. Это не повод критиковать наличие шасси у самолёта. Это нужно и это удобно. Так же и тут.
                                                                                                      Вам верность лингвистическому определению или практическая польза важна? Сколько вы пишете на Go, кстати?

                                                                                                      Про Go, в котором комментарии были заменены на метаданные.

                                                                                                      В Go не заменяли комментарии на метаданные.

                                                                                                      • +3
                                                                                                        Я к ней аппелирую, потому что это один из моментов, по которым принимаются решения. Уже писал, что дизайн языка — это не черное и белое, и не бинарный выбор «очевидно, что это должно быть так» и «не так». Неужели это и вправду нужно разъяснять 15 комментариев подряд?

                                                                                                        А прямая совместимость бинарная. Она или есть, или ее нет. Как я понял, в Go ее нет. Смысла на ее ориентироваться нет, раз ее нет.
                                                                                                        Вы просто привели бесполезный аргумент и все.
                                                                                                        В Go не заменяли комментарии на метаданные.

                                                                                                        Комментарий не меняет семантику программы. То, что выглядит как комментарий в Go ее меняет. Следовательно, это не комментарий.

                                                                                                        По определению самолёт — должен летать.

                                                                                                        В нашем случае, самолет совершает телепортацию, а не летает.

                                                                                                        И я не пишу на Go. Но от этого проблема того, что Go лишь делает вид, что в нем есть комментарии не исчезнет.
                                                                                                        • +5
                                                                                                          Сколько вы пишете на Go, кстати?

                                                                                                          А вот и пошли аргументы в стиле «сначала добейся».

                                                                                                          Чето все мелочи всякие обсуждаем. Может начать тему того, что в го отсутствует система управления зависимостями и намеченное решение выглядят как большой такой и страшный костыль, который все равно ее не решает. Такой то системный язык для больших команд и проектов. Благо хоть создатели осознают, что это большой фейл и надо с ним что-то делать. Жалко, что сами они не хотят с этим ничего делать.
                                                                                                          • –1
                                                                                                            А вот и пошли аргументы в стиле «сначала добейся».

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

                                                                                                              Плохие практики в разных языках так же отлично решают свои задачи.
                                                                                                              Например, что бы понимать, что generic в Java сделаны плохо, не обязательно иметь опыт работы с ней. Они объективно плохи.

                                                                                                              Так же, как решение заменить комментарии на некую другую сущность.
                                                                                                              • +1
                                                                                                                Дизайн generics в java с type erasure оправдан. Реализация позволяет сохранить прямую и обратную совместимость с 1.4, что для enterprise-пользователей является очень существенным фактором.

                                                                                                                Т. е. в библиотеку, написанную и скомпилированную под java 1.4 можно передавать generic-объекты из кода под 1.5 и наоборот.

                                                                                                                То, что они могут быть субъективно плохи в ваших задачах не означает, что они плохи для всех. Так что никакой объективностью тут и не пахнет.
                                                                                                                • 0
                                                                                                                  Дизайн generics в java с type erasure оправдан. Реализация позволяет сохранить прямую и обратную совместимость с 1.4, что для enterprise-пользователей является очень существенным фактором.


                                                                                                                  Это не отменяет того факта, что generics в java — костыль. Единственная причина, по которой их сделали именно так — недальновидность создателей первой версии Java.

                                                                                                                  То, что они могут быть субъективно плохи в ваших задачах не означает, что они плохи для всех.


                                                                                                                  Приведите пример задачи, в которой type erasure выгоднее по сравнению с нормальными generics (как в C#).
                                                                                                                  • +1
                                                                                                                    Единственная причина, по которой их сделали именно так — недальновидность создателей первой версии Java.
                                                                                                                    Если пытаетесь намекать на дальновидность разработчиков .NET, который появился в 2000, то стоит посмотреть на то, что java появилась в 1995.

                                                                                                                    В C# generics появились тоже не сразу (2006, против 2004, когда они появились в java). И в случае .NET как-то не очень заморачивались совместимостью .NET 1.1 и 2.0.

                                                                                                                    У Java иной подход — сохранение совместимости. И во всех задачах, когда была необходимость использовать старый код в новом окружении (без какой-либо модификации и перекомпиляции) type erasure выигрывает по сравнению с переписыванием кода или запуском его различных кусков под разными версиями CLR.
                                                                                                                    • +3
                                                                                                                      Однако параметрический полиморфизм, то, что в java почему-то назвается Generics, (без подтипирования) появился аж в 1975 году, так что это не оправдание. Кстати, это же объясняет почему, в Go его нету, туда настолько молодые фичи не попадают.
                                                                                                                      • 0
                                                                                                                        Опять отмазки пошли.

                                                                                                                        Я знаю, что java появилась давно. Я знаю, что обратная совместимость и бла-бла-бла.

                                                                                                                        В Java всегда так: вместо решения проблемы сначала говорят «нам не нужны шаблоны / передача функций как аргументы / множественное наследование», а потом приходится прикручивать костыли, ибо обратная совместимость. А потом адепты затыкают уши, когда критикуют их любимую джаву.

                                                                                                                        Если бы Java проектировали сегодня, никто бы не делал type erasure.
                                                                                                                        • 0
                                                                                                                          То, что они могут быть субъективно плохи в ваших задачах не означает, что они плохи для всех. Так что никакой объективностью тут и не пахнет.

                                                                                                                          Приведите пример задачи, в которой type erasure выгоднее по сравнению с нормальными generics (как в C#).
                                                                              • +1
                                                                                Об этом я даже не подумал :)
                                                                                В первую очередь меня смущает то, что может найтись чудак (особенно учитывая целевую аудиторию Go — тех, кого нужно «научить по-быстрому»), который напишет вот так:
                                                                                //Hey! Look at my awesome function Blabla
                                                                                //go:generate toolname -params -blabla
                                                                                //Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                                                                                //Donec tortor erat, rhoncus ac turpis id, ullamcorper congue odio
                                                                                func Blabla() {
                                                                                    // code...
                                                                                }
                                                                                


                                                                                Ну прямо ОЧЕНЬ заметно, что тут аннотация в комментариях. В общем, в других языках, которые тоже компетентные люди проектируют, такие вещи выделяют в отдельные сущности, Пайк же посчитал, что это СЛОЖНО. Ну ок, я его понял, но по-моему технология для инженеров не должна ориентироваться на дебилов…
                                                                                • –1
                                                                                  Если бы вы писали на Go, вы бы понимали, почему нет оснований полагать, что кто-нибудь так напишет. А если и напишет, то ничего страшного не произойдет. С таким же успехом можно говорить «Tesla — плохой автомобиль, потому что кто-то можно положить пальто на тачскрин и не сможет его видеть». Попробуйте на практике и судите о дизайне по делу, а не по придуманным кейсам.
                                                                                  • +1
                                                                                    Конкретно насчёт этого я сейчас немного разобрался и понимаю, что неправ.
                                                                            • +10
                                                                              Тем что это части синтаксиса языка.

                                                                              Почему-то мало кто понимает, что «магические комментарии» в Go — это вообще не комментарии. go generate не парсит go-код, она тупо ищет подстроку. Посмотрите вот на такой код: http://play.golang.org/p/BwHvNiZggA — go generate найдёт тут свою инструкцию и попробует её исполнить, хотя она и не в комментарии.

                                                                              Я люблю Go, но вот это конкретное место — это очень плохой дизайн. Имхо.
                                                                          • 0
                                                                            Автогенерация кода тоже костыль. См. хаскелевские template haskell (который на самом деле тоже кривоват и костыль) и generics.
                                                                            • +1
                                                                              TH это, кстати канонический пример костыля, т.к. радостно ломает абстракции (скрывает типы за ExpQ), в отличии от Generics, и даже появляющийся Typed-TH не очень поможет в силу ограничений. (Правда в отличии от generics позволяет генерировать более эффективный код, с расширениями generics такое тоже возможно, но уже не так просто). Естественно плюс TH, в отличии от, насколько я понимаю, go, в том, что генерация производится средствами языка, что не мешает вызывать внешние утилиты если необходимо. А совсем хороший вариант в MetaOcaml, например.
                                                                              • 0
                                                                                Именно. Даже костыльный TH лучше условного {-# hask-henerate ...#-}.
                                                                                Хотя стоп, какие {-#, у нас же нет прагм, пусть будет обычный --.

                                                                                А MetaOcaml я не тыкал :(
                                                                          • +2
                                                                            Магические комментарии — это костыль. Претензии к тому, КАК сделали.
                                                                            Лучший критический комментарий за два поста, imho.
                                                                            • 0
                                                                              «Костыль» — это ярлык, не более. Shebang — это тоже такой-же «костыль», что не мешаем ему исправно выполнять свою функцию на всех UNIX-системах, не так ли?
                                                                              Так что важнее — практическая польза или чей-то ярлык «костыля»? Какие реальные практические проблемы с go generate были хотя бы у одного из комментаторов тут? Да ни у кого.

                                                                              Конкретно по поводу go generate — был пропозал и были дискуссии о том, как лучше решить проблему. В дискуссии мог поучаствовать каждый хабровчанин и предложить «не костыль», обосновав, почему его «не костыль» будет хорошим дизайном.
                                                                              • +1
                                                                                Костыль, но имеющий четко определенное место. Он идёт первой строкой в самом начале файла. Его сложно не заметить и тем боле спутать с чем-то другим.
                                                                                Аналогично другой костыль — указание кодировки файла для python 2. Тоже расположен в первой или второй строке и только там.
                                                                          • +7
                                                                            По сути дела они придумали препроцессор, но сделали вид, что они не при делах.
                                                                            • +1
                                                                              с make сравнили бы ещё ладно, но это не препроцессор
                                                                              • +4
                                                                                По факту ведь берется этот файл с магическими комментариями и на основе него генерируется другой, новый файл. Это ли не препроцессор в чистом виде?
                                                                                При помощи make тоже можно препроцессор к любому языку программирования приделать.
                                                                                • 0
                                                                                  По факту запускается любая команда, это как тоже самое, что сказать make или bash это препроцессор.
                                                                                  Эти запуски не как не связаны с процессом компиляции, в зависимостях которые вы ставите они не вызываются, только запуски руками.
                                                                                  Почитайте https://blog.golang.org/generate, возможно просто я плохо объясняю.
                                                                                  • +2
                                                                                    Ну просто получается, что необходимость в кодогенерации нужна, то есть по факту нужны обобщения, но их нет в языке и нет никакого стандарта на них.
                                                                                    Вот тебе и плата за простоту.
                                                                                    • 0
                                                                                      Не всё что решается генерацией можно решить обобщенным программированием. Примеры с генерацией парсеров и тп.
                                                                                      • 0
                                                                                        Думается мне, что такие вещи нужно решать через генераторы парсеров, которые вообще на другом языке написаны, специально для этого созданном, а не встраивать их в комментарии.
                                                                                        • 0
                                                                                          ну если вы начнете читать, что вам люди пишут может даже диалог получится.
                                                                                          //go:generate go tool yacc -o gopher.go -p parser gopher.y
                                                                                          как думаете что такое yacc?
                                                                                          • +2
                                                                                            yet another compiler compiler — генератор парсеров?
                                                                                            • 0
                                                                                              Отсюда:
                                                                                              Yacc is a computer program for the Unix operating system. The name is an acronym for «Yet Another Compiler Compiler». It is a LALR parser generator

                                                                                          • +1
                                                                                            Этим другим языком вполне может быть eDSL. И это как-то лучше и удобнее, чем дёргать действительно другие языки.
                                                                                          • +3
                                                                                            Ну вот Boost.Spirit обходится без препроцессоров.
                                                                                            • +3
                                                                                              Даже parsec обходится без препроцессоров!
                                                                            • +22
                                                                              Видимо автор этой статьи знает и умеет в Go, но вот эти обиды, нападки на другие языки и «неверных» можно было бы и опустить.
                                                                              • –2
                                                                                Нападки на языки — это упоминание С++ в эпилоге?
                                                                                • +1
                                                                                  По-видимому, Вы пропустили мой комментарий ( хотя это неудивительно, их тут уже 120+ ).
                                                                                  • –3
                                                                                    Просто все, кто писал на C++, переключившись на другие языки — изливают накопившуюся боль оттого, что столько лет провели на темной стороне силы :)
                                                                                    • +2
                                                                                      Я писал на C++, теперь на C++ и Haskell, но отчего-то боли не ощущаю :)
                                                                              • –17
                                                                                Go никому не нужен.
                                                                                Программист C++ легко освоит его, это да.
                                                                                Но в обратном я сомневаюсь.
                                                                                • +5
                                                                                  Уместней было бы сказать «легче». Зачем вешать неуместные ярлыки на людей.
                                                                                  А по части нужности судить не вам думаю.
                                                                                  • –11
                                                                                    После того как меня «отхабрили» в предыдущем обсуждении Go, мне стало все равно.
                                                                                    • +13
                                                                                      Назвав собеседников хомячками вы чего-то другого ожидали?
                                                                                      • +8
                                                                                        То есть, Go — плохой из-за того, что вас «отхабрили»? ))
                                                                                    • +5
                                                                                      Это пост любви к Go, тут нельзя так грубо.
                                                                                    • +1
                                                                                      а чёрт надо кофе с утра больше пить
                                                                                      • 0
                                                                                        Эм, не стоит, тем более в выходной.