Постулаты Go

    В игре Go очень простые правила, но стать мастером в ней непросто, нужно научиться думать паттернами, территориями и прочими стратегическими концепциями. Язык Go не совсем случайно назван аналогично названию этой игры. В своем выступлении на недавнем митапе в Сан-Франциско, Роб Пайк упомянул книгу «Постулаты Go» (Go Proverbs), которые описывают сложные стратегии простыми поэтичными фразами. Эти постулаты несут глубинный смысл для тех, кто знаком с игрой Go, и могут казаться пустыми фразами тем, кто не знаком. И в этом нетехническом докладе он предложил придумать аналогичным способом «постулаты» и для языка Go.

    Вот некоторые из них:
    • Don't communicate by sharing memory, share memory by communicating.
    • Concurrency is not parallelism.
    • Channels orchestrate; mutexes serialize.
    • The bigger the interface, the weaker the abstraction.
    • interface{} says nothing.
    • Gofmt's style is no one's favorite, yet gofmt is everyone's favorite.
    • A little copying is better than a little dependency.
    • Cgo is not Go.
    • Clear is better than clever.
    • Reflection is never clear.
    • Errors are values.


    Это чем-то похоже на Zen of Python. Вы можете не соглашаться с ними, но эти постулаты отражают идиоматичность и подход в Go. Давайте разберем подробнее каждый из них по мотивам доклада (видео в конце поста).


    «Не общайтесь разделением памяти. Разделяйте память через общение.» (Don't communicate by sharing memory, share memory by communicating)
    Этот постулат знают все, он звучал неоднократно в докладах и постах посвященным паттернам конкурентного программирования в Go. Этот постулат призван дать понимание сути механизма работы каналов и горутин — ваши функции не делят одну и ту же память, они безопасно общаются, передавая данные по каналам.

    «Конкурентность — это не параллелизм» (Concurrency is not parallelism)
    Не уверен, что слово concurrency сколько-нибудь удачно переводится на русский, но суть в том, что параллелизм — это просто параллельное выполнение одного и того же кода, а софт, полноценно использующий преимущества многоядерности — конкурентный софт — это конкурентность, тоесть способ структурироания логики программы. Новички очень часто путают эти два понятия. Есть отличное выступление Пайка с одноименным названием, обязательно посмотрите, кто ещё не.

    Каналы — оркестрируют, мьютексы — сериализируют (Channels orchestrate; mutexes serialize)
    Хороший постулат в тему предыдущей статье («Танцы с мьютексами в Go»), о том, когда использовать мьютексы, а когда каналы. Мьютексы просто сериализируют исполнение доступа к чему-либо, но горутины и каналы дают вам инструмент создавать программы со сложной архитектурой и структурой обмена данными между частями программы.

    Чем больше интерфейс, тем слабее абстракция (The bigger the interface, the weaker the abstraction)
    Новички в Go, особенно пришедшие с Java, часто считают, что интерфейсы должны быть большими и содержать много методов. Также часто их смущает неявное удовлетворение интерфейсов. Но самое важное в интерфейсах не это, а культура вокруг них, которая отображена в этом постулате. Чем меньше интерфейс, тем более он полезен. Пайк шутит, что три самых полезных интерфейса, которые он написал — io.Reader, io.Writer и interface{} — на троих в среднем имеют 0.666 метода.

    Делайте нулевое значение полезным (Make the zero value useful)
    Речь о том, что лучше делать нулевое значение типов полезным безо всяких конструкторов. Конечно, иногда функции-конструкторы необходимы, но если есть возможность сделать переменную вашего типа рабочей «прямо из коробки» — это всегда идёт на пользу. Пример — тип bytes.Buffer или sync.Mytex из стандартной библиотеки. Пустое значение — это готовый к использованию буфер, хотя и существуют конструкторы вроде bytes.NewBuffer и bytes.NewBufferString().

    Пустой интерфейс ни о чём не говорит (interface{} says nothing)
    Этот постулат говорит о том, что интерфейсы — «поведенческие типы» — должны что-то означать. Если вы создаёте интерфейс, это что-то означает и служит конкретной цели. Пустой же интерфейс (interface{}) ничего не означает и ни о чём не говорит. Есть ситуации, когда его нужно использовать, но они чаще исключение — не используйте interface{} без повода. Новички часто переиспользуют пустые интерфейсы, и масса вопросов на Stack Overflow именно о них.

    Стиль Gofmt — это не чье-то предпочтение, но gofmt предпочитают все (Gofmt's style is no one's favorite, yet gofmt is everyone's favorite)
    Многие новички, борясь с привычками, жалуются на то, что код в Go отформатирован не так, как им нравится. Gofmt — это единый стиль, он не является чьим-то личным предпочтением. Даже сам Грисмайер, автор утилиты go fmt, сам предпочёл бы другой стиль форматирования. Но с того момента, как формат был утверждён и gofmt используется везде и всегда — просто примите это как должное. Опытные программисты считают go fmt спасением, так как он очень упрощает работу с чужим кодом — ад с разными стилями форматирования в других языках ушёл в прошлое.
    Примечательно, что новые языки перенимают этот подход (к примеру, rustfmt) — это то, о чём говорил Dave Cheney в своем выступлении «Наследие Go» — новые языки больше не будут считаться полноценными без единого стиля форматирования и утилиты, обеспечивающей это.

    Небольшое копирование лучше небольшой зависимости (A little copying is better than a little dependency)
    Это уже относится к программированию в целом, но в Go это видно и по стандартной библиотеке, и в культуре в целом. Отчасти это перекликается с известной установкой «Дупликация дешевле плохой абстракции». Пайк рассказывает, как в первые дни в Google ему сказали, что больше всего пекутся о реиспользовании кода. Если можно избежать написания одной повторяющейся строчки, сделав импорт — нужно так и поступать. По мнению Пайка, Google до сих пор разгребает проблемы с кодом из-за этого подхода. Очень часто функционал может быть похож (до первого рефакторинга), или необходима лишь часть функционала из зависимости, и зачастую бывает эффективней написать 5 строчек, чем импортировать 150кб зависимостей. Как пример — функция IsPrint из пакета strconv — она дублирует функционал unicode.IsPrint(), при этом тесты проверяют, что функции работают одинаково. Резюмируя — не бойтесь копирования кода, там где это оправдано.

    Код с syscall-вызовы должен содержать build-теги (Syscall must always be guarded by build tags)
    В тему недавно переведённой статьи «Как писать Go код, который легко портируется». Некоторые жалуются на пакет syscall в Go — нужно его изменить, он не портируется. Но syscall-ы это по определению платформозависимые вызовы, поэтому если вы хотите делать качественный кроссплатформенный код — всегда добавляйте build-теги в файлы, в которых используются syscall.

    Cgo также должны содержать build-теги (Cgo must always be guarded by build tags)
    По абсолютно той же причине — всегда добавляйте build-теги, при использовании cgo. Если вы вызываете С — никто не знает, что там на самом деле происходит, это почти наверняка непортируемо.

    Cgo это не Go (Cgo is not go)
    Многие радуются тому, как легко в Go использовать C-код. Иногда, это, конечно, необходимо, но Пайк признается, что сам никогда не использовал Cgo, и в мире Go есть четкое понимание памяти, стабильность, безопасность, сборка мусора… и с Cgo всё это идёт в топку. В 90% случаев в Google, когда кто-то говорит «моя программа крашнулась, помогите разобраться» — дело оказывается в Cgo.

    С пакетом unsafe нет гарантий (With the unsafe package there are no guarantees)
    Тут делается акцент на том, что код написанный с использованием пакета unsafe также не портируемый, и на него не распространяются гарантии обратной совместимости в пределах Go 1 (это написано в первой же строке документации к пакету). Пока что в нём ничего не меняли, но если вы собираетесь использовать зачем-то unsafe — будьте готовы, что в будущих версиях, придётся подстраиваться под изменения.

    Ясно лучше, чем заумно (Clear is better than clever)
    Постулат о том, что в Go ясность и читабельность кода стоит на первом месте. И вы должны также стремиться писать ясный и понятный код, вместо заумного. Ваш код рано или поздно будут читать, улучшать и рефакторить другие программисты, и чем яснее он будет, тем проще и быстрее будет результат. Go будет всеми способами и силами вам в этом помогать и способствовать, весь дизайн языка пропитан этой целью.

    Рефлексия никогда не понятна (Reflection is never clear)
    Рефлексия (способность программы менять собственную структуру) в Go реализована пакетом reflect, и люди нередко пытаются использовать её не к месту. Рефлексия — это очень-очень мощная вещь, но очень сложная для понимания, и на самом деле нужна очень малому количеству людей и задач. Пайк говорит, что написал, вероятно, больше всех кода с рефлексией в Go, и до сих пор ненавидит это делать. И считает, что нужно стимулировать людей не использовать рефлексию, поскольку она, как правило, не нужна так, как им это кажется.

    Ошибки это значения (Errors are values)
    Ещё один важный постулат, который уже неоднократно освещался на хабре, и которому, в частности, посвящена статья в официальном блоге Go. Новички часто не понимают этого и спрашивают — «почему я должен везде писать эти if err != nil». Да потому что вы не программируете, вы клепаете код. Многие считают, что if err != nil — это такая альтернатива try..catch… — специальная конструкция языка для работы с ошибками. Но это не так, вы не можете программировать с try… catch… — это управляющая конструкция. С ошибками же в Go можно и нужно делать то, что требует логика программы.

    Не просто проверяйте ошибки, обрабатывайте их красиво (Dont’ just check errors, handle them gracefully)
    Ошибки очень важно не просто проверять, но и думать, что с ними делать, чтобы ошибочная ситуация была обработана корректно. Возможно нужно дополнить ошибку какой-то информацией, возможно запомнить для обработки позднее, что-нибудь ещё. Огромная и очень важная часть программирования — это как вы обрабатываете ошибки. Не просто проверять и пробрасывать наверх, а думать о том, как правильно обработать эту ошибку. Это справедливо для всех языков, но поскольку в Go ошибки это просто значения, то это проще сделать и проще реализовать красивую и правильную обработку ошибок в коде.

    Продумывайте архитектуру, называйте компоненты, документируйте детали (Design the architecture, name the components, document the details)
    Тут речь о важности правильного именования компонентов вашего кода, методов, функций и переменных. Эти имена будут потом находится в коде пользователей вашего пакета. И если имена удачны и понятны, дизайн программы будет более ясен и прост для понимания. Но, конечно, всегда есть детали, которые нужно объяснить — и вот их нужно помещать в документацию.

    Документация — для пользователей (Documentation is for users)
    О том, что документация к функции должна описывать не что эта функция делает, а для чего она нужна. Это очень важное различие, которое зачастую упускается из виду. Когда пишете документацию, посмотрите на неё глазами пользователя вашего пакета.

    Ну, и если вы можете придумать ещё какие-то постулаты, которые удовлетворяют критериям краткости, поэтичности и концептуальности — смело предлагайте.

    go-proverbs.github.io

    Слайды (не оригинальные, правда): speakerdeck.com/ajstarks/go-proverbs

    Видео:
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 77

      +9
      Документация — для пользователей (Documentation is for users)

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

        Не стесняйтесь и выступайте с докладами о том, как нужно писать документацию. Мастер всегда должен делиться знаниями с начинающими. Думаю, авторам Go пойдут на пользу ваши уроки.
        +3
        > Не общайтесь разделением памяти. Разделяйте память через общение.
        > Каналы — оркестрируют, мьютексы — сериализируют

        Зачем мьютексы в отсутствии разделяемой памяти?

        > «Конкурентность — это не параллелизм»

        Многозадачность.

        > Чем больше интерфейс, тем слабее абстракция

        А смысл редуцировать все интерфейсы до одного метода? Не проще ли сразу фигачить сигнатуры этих методов?

        > Стиль Gofmt — это не чье-то предпочтение, но gofmt предпочитают все

        Смысл делать его тогда отдельным тулом? Внесите эти правила в спеку и пусть компилятор ругается.

        > Как пример — функция IsPrint из пакета strconv — она дублирует функционал unicode.IsPrint(), при этом тесты проверяют, что функции работают одинаково.

        И что хорошего в этом индусском подходе?

        > Пайк говорит, что написал, вероятно, больше всех кода с рефлексией в Go, и до сих пор ненавидит это делать.

        Значит ему стоило поработать над этим аспектом языка, чтобы он стал простым и понятным.
          0
          Зачем мьютексы в отсутствии разделяемой памяти?

          Где сказано, что в Go нет разделяемой памяти?

          А смысл редуцировать все интерфейсы до одного метода? Не проще ли сразу фигачить сигнатуры этих методов?

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

          Смысл делать его тогда отдельным тулом? Внесите эти правила в спеку и пусть компилятор ругается.

          Тул форматирует код, делая эту работу за человека.

          Значит ему стоило поработать над этим аспектом языка, чтобы он стал простым и понятным.

          Простите ему, он не так мудр. А потом почитайте про essential complexity.
            0
            > Где сказано, что в Go нет разделяемой памяти?
            тут:
            > ваши функции не делят одну и ту же память, они безопасно общаются, передавая данные по каналам.

            То, что это не правда уже понятно, раз есть мьютексы :-D Похоже постулаты можно нарушать, если ты Роб Пайк.

            > Суть интерфейса — описывать поведение. Если у вас просто тип с «нафигаченными» методами — то это не интерфейс, это просто тип с методами. Если же может быть много типов, реализующих определённое поведение, то тут место интерфейсу и количество методов интерфейса будет стремиться к минимуму.

            У интерфейсов есть 2 функции:
            1. идентификационная (в го не используется)
            2. группировочная (в го не рекомендуется)

            Так зачем в го интерфейсы, если достаточно сигнатур?

            > Тул форматирует код, делая эту работу за человека.

            Почему компилятор позволяет писать неотформатированно?

            > Простите ему, он не так мудр. А потом почитайте про essential complexity.

            Жду статью про essential complexity рефлексии :-)
              0
              У интерфейсов есть 2 функции:
              1. идентификационная (в го не используется)
              2. группировочная (в го не рекомендуется)
              «Идентификационной функцией» вроде как пользуются в стандартной либе повсеместно (io.Reader, io.Writer, fmt.Stringer). На счет «группировочной функции» тоже не понятно. Вроде как есть рекомендации не делать интерфейсы большими. Рекомендации избегать группировки методов или интерфейсов в одном интерфейсе вроде нет.

              P. S.: может не понял, что вы в эти два понятия вкладываете.
                –1
                1. Может быть множество равных интерфейсов с разными именами, вы не можете отличить io.Reader от my.Reader если в них объявлены одинаковые сигнатуры
                2. Есть рекомендация минимизировать число сигнатур вплоть до одного метода
                  0
                  Зачем мне отличать io.Reader от my.Reader, если мне нужно всего то совершить некое действие? Мне важно чтоб обьект поддерживал это действие, кто он мне глубоко не важно и не нужно их идентифицировать. В го это прекрасно работает.
                    +1
                    Поэтому я и написал, что в го идентификационная функция не используется в отличие от других языков.
                    Два эти метода могут иметь одинаковые сигнатуры, но совершенно различную семантику. Вы можете явно или неявно воспользоваться таким методом не в том контексте и го не выявит такую ошибку на этапе компиляции. В лучшем случае она будет обнаружена тестами.
                      0
                      Так это правильно, мне не важно как он будет делать свои дела, мне важно чтоб он сделал определенное действие. Мне кажется это логичным действием для интерфейса, он не должен указывать как, он должен указывать что. А по поводу контекста, это уже вопросы к архитектуре и способностям программиста следить за тем что он делает. Никто ведь не ругает си за указатели, это мощная штуковина, но ей нужно грамотно пользоваться, тоже и с интерфейсами в го, ими нужно грамотно пользоваться а не как попало. Нужно продумывать интерфейсы, это большая часть философии языка, они не такие как в других языках и это нужно учитывать, это не плохо и не хорошо, это просто по другому.
                        +3
                        По поему вы вообще говорите о разном. vintage говорит о том, что в языках C# и Java интерфейс — это не просто множество функций, которые могут быть реализованы для того или иного объекта, но ещё и «метка»: да, этот объект действительно пригоден для использования в определённом качестве. Интерфейс Cloneable вообще ни одного метода не содержит, что не делает его бессмысленным!

                        Хорошо это или плохо? Я бы сказал что конкретно в языках C# и/или Java этот подход выглядит… странно. Потому что они во-многом являются наследниками С, а на Pascal'я. В наследниках Pascal'я (Oberon или какая-нибудь Ada) вариант, который реализован в Java был бы вполне естественнен: там даже функция, принимающая массив из 10 элементов может не принять массив из 10 элементов если это — другой массив (в смысле массив другого типа)! В C++ интерфейсов, строго говоря нет, так что обсуждать их бессмысленно, но когда их предлагали добавить, то, разумеется, предлагалась версия в стиле C, а не версия в стиле Pascal'я!

                        Практически же в Java я встречался с тем, что объект не реализует нужный мне интерфейс гораздо чаще (это обходится путём прикручивания кучки костылей), чем в Go с тем, что объект «как бы реализует» нужный мне метод — но неправильно. Опасность такого теоретически — довольно-таки велика, но практически — вы должны очень сильно не понимать, что вы делаете, чтобы на это нарваться.

                        Это обозначает, по большому счёту, что для «генетического программирования» (в программе объединяются куски со StackOverflow в случайной последовательности пока не начинают проходить тесты, после чего код отправляется в production) язык Go подходит не так хорошо, как Java. Я вообще не уверен, что поддержка подобного стиля программирования — то, к чему стоит стремиться, но то, что Go для него не подходит — правда, тут как бы особо и спорить не о чем.
                          0
                          Да, я это и имел ввиду, сам пишу на PHP и там в интерфейсы вкладывают то же что и vintage имеет ввиду, по интерфейсу можно так же идентифицировать прибывший обьект, поэтому я такое поведение знаю хорошо. с другой стороны и понимаю почему в го изменили саму сущность интерфейсов, для него такой тип не подходит. Может я просто не так выразился :)
                          0
                          Вообще-то си ещё как ругают за указатели и именно потому, что с ними легко не просто прострелить себе ногу, а скастовать чёрную дыру. И мы до сих пор огребаем проблемы с безопасностью из-за того, что кто-то на заре юникс подумал «а давайте сделаем вот такую мощную штуку с которой нужно грамотно обращаться, а не как попало».

                          Касательно структурной типизации — вопрос далеко не только в частоте срабатывания зарядов, а в последствиях их взрывов. Использование неверного метода будет проглочено молча и вылезет вам боком в совершенно неожиданном месте. При этом использование это будет даже не вами, а где-то в глубинах используемой вами библиотеки. А несоответствие интерфейсов в той же яве вызовет ошибку компиляции и потребует явно сказать компилятору, что вы хотите получить. Другое дело, что нужны более прямые механизмы сообщить компилятору, какие интерфейсы совместимы.
                  +2
                  То, что это не правда уже понятно, раз есть мьютексы :-D Похоже постулаты можно нарушать, если ты Роб Пайк.

                  Вы либо не хотите понять, о чём речь, либо хотите, но не получается. Постулат призван помочь понять подход CSP (с каналами и рутинами), а не запретить использовать мьютексы.

                  Так зачем в го интерфейсы, если достаточно сигнатур?

                  Достаточно для чего? Интерфейс — это «строительный блок», помогающий создавать красивые архитектуры. Возьмите тот же io.Reader, с которым работают многие функции стандартной библиотеки. К примеру, декодер JSON принимает как параметр io.Reader, и ваша программа туда может передавать всё что удовлетворяет io.Reader — файл, тело http-ответа, стрим из сокета, буфер или что угодно.
                  Ещё раз — интерфейс это не «идентификация методов», это строительный блок программы. И, как и в философии UNIX, маленькие блоки, описывающие одну операцию, позволяют строить разнообразные и сложные конструкции.

                  Почему компилятор позволяет писать неотформатированно?

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

                    0
                    Один постулат говорит не разделять состояние, а использовать каналы, а другой предлагает его разделять в дополнение к каналам. Двойные стандарты.

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

                    Какжеэтоутомительновручнуюрасставлятьпробелы, да.
                      +1
                      Один постулат говорит не разделять состояние, а использовать каналы, а другой предлагает его разделять в дополнение к каналам. Двойные стандарты.

                      Это не двойные стандарты, а умение применять нужный инструмент для нужного случая. Неужели это такая сложная концепция для вас?

                      Так вот, однометодный интерфейс в го — это не более чем именованный алиас для сигнатуры, делающий оную менее явной (нужно идти к определению интерфейса и смотреть что он там получает-возвращает). А как же принцип «Ясно лучше, чем заумно»?

                      Вы сейчас о чём-то о своем рассказываете, весьма пространном, и, соответственно, делаете странные выводы

                      Какжеэтоутомительновручнуюрасставлятьпробелы

                      Не понимаю вашего паясничания. Будьте добры, засеките сколько времени у вас займёт преобразовать вот такой простой плохочитаемый пример:
                      type User struct {
                          ID int64 // user id
                          Name          string              // user first name
                         Surname    string      // given name
                          Birth      time.Time              // user birthdate
                      }
                      

                      вот в такой:
                      type User struct {
                      	ID      int64     // user id
                      	Name    string    // user first name
                      	Surname string    // given name
                      	Birth   time.Time // user birthdate
                      }
                      

                      У go fmt это занимает миллисекунды, если что. Именно поэтому go fmt обычно стоит как hook на сохранении файла в редакторе/IDE.
                        –2
                        В таком случае это никакие не постулаты. И вообще всю статью можно было бы свести к «думай головой» и не морочить голову протекающими принципами.

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

                        И часто вы пишете такой простой плохочитаемый код? :-D это ж ещё не полениться надо столько пробелов понаставить…
                          +2
                          И часто вы пишете такой простой плохочитаемый код? :-D это ж ещё не полениться надо столько пробелов понаставить…

                          Я всегда ставлю ровно один пробел, прежде чем начать комментарий. Из-за того, что названия полей и типов разной длины, все комментарии оказыаются в разном месте, так что да, вручную я комментарии для «читаемости» на ставлю.
                            –2
                            Вертикальное выравнивание — это не читаемость, а блажь, от которой больше проблем, чем пользы.
                              +2
                              Так и знал, что вам первый пример кода более близок.
                            +1
                            я, вот, например, тоже не могу понять ваши придирки к постулату про мьютексы-каналы. очевидно, что применимы могут быть оба подхода в разных ситуация, просто один для примитивных случаев, а второй для более сложной логики, вот и все.
                            попахивает троллингом каким-то с вашей стороны :)
                            0
                            Такое форматирование плохо с точки зрения системы контроля версий. Если длина самой длинной переменной изменится, то будет изменена не одна строка, а четыре. Соответственно, в комит попадут строки, не относящиеся к изменению.
                              0
                              Это правда, но это на практике такая мелочь по сравнению с тем ужасом, который случается с кодом, когда разные программисты с разными предпочтениями меняют код в течении нескольких лет. Кстати, бывший коллега, когда ещё не писал на Go, но активно пытался найти изъяны — тоже этот довод использовал. После года реальной работы с Go этот «изъян» ни разу не дал о себе знать и не составил проблемы, зато теперь понимает, что код, всегда аккуратно выглядящий благодаря go fmt — это бесценно.
                                0
                                Не вижу никаких сложностей прочитать код без вертикального выравнивания.

                                type User struct {
                                    // user id
                                    ID int64
                                    // user first name
                                    Name string
                                    // given name
                                    Surname string
                                    // user birthdate
                                    Birth time.Time
                                }
                                


                                А вот правильная работа с системой контроля версий — объективная необходимость тех, кто регулярно проводит обзор кода.

                                … программисты… меняют код в течении нескольких лет ...

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

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

                                  Я не вижу никаких сложностей так писать код, если это настолько критичная для вашей работы вещь, что вы готовы отказаться от такого удобного инструмента, как go fmt.
                                    0
                                    Субъективные настройки форматирования для вас настолько критичная вещь, что вы готовы отказаться от нормальной работы с СКВ?
                                      0
                                      Это не «субъективные настройки», это отсутствие ада, с которым приходилось сталкиваться раньше в других языках. И да, для меня это важнее, чем «чуть менее удобное представление части диффа в 1% случаев, при необходимости их внимательно инспектировать». Код я пишу чаще, чем анализирую диффы, и такое мелкое отличие, которое отнюдь не требует «телепатии», несравнимо с гарантией нормально отформатированного кода.
                                      Если честно, не представляю, почему для кого-то может быть иначе, кроме как если ваша основная работа — код ревью. Но и тогда, будь у вас опыт с go fmt, вы, по идее, больше всех оценили бы его эффект в реальной практике.
                                        –1
                                        Я не понимаю, почему я вообще обязан идти на компромисс: либо общий стиль оформления, либо нормальные комиты.

                                        Для других языков, например (внезапно), C++, тоже есть инструменты для автоформатирования. При этом эти инструменты не зависят от хотелок какого-то конкретного человека. Каждая команда может установить свой стиль и «нормально» форматировать код в рамках команды/проекта/компании.

                                        То, что весь в мире код не будет выглядеть одинаково — это тоже не недостаток, а преимущество. У одних людей одни приоритеты (например, работа с СКВ), у других — другие (например, нескучное вертикальное выравнивание). И каждый может получить то, что ему нужно.

                                        Не надо выдавать недостаток за преимущество.
                                          0
                                          Я не понимаю, почему я вообще обязан идти на компромисс

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

                                          При этом эти инструменты не зависят от хотелок какого-то конкретного человека. Каждая команда может установить свой стиль и «нормально» форматировать код в рамках команды/проекта/компании.

                                          Ха-ха, а от кого же они зависят? Вот приходите вы в новую компанию, а там тим-лид установил «стиль», который вам неприятен/неудобен. В Go такой проблемы нет — стиль один и темы «а я люблю/хочу вот так» нету в принципе.
                                          Ну и не говоря уже о том, что написание code guide для С++ — это та ещё забава, которая вводится обычно после большой боли, вызванной тем, что вы называете «преимуществом». А соблюдать большой команде эти code guide-ы — это тоже отдельная забава, отнимающая и без того излишне отнятое время при С++ разработке.
                                          Я лично за 10+ лет натерпелся этого вдоволь, так что нет, спасибо.

                                          Не надо выдавать недостаток за преимущество.

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

                                            Нет ни одного плюса в том, что каждый человек/тим пишет код так, как это позволяет его фантазия/квалификация.

                                            В Go такой проблемы нет — стиль один и темы «а я люблю/хочу вот так» нету в принципе.

                                            … это однозначно преимущество, тут даже сомневаться не в чем ...


                                            Зря я затеял разговор с религиозным фанатиком.
                                              +1
                                              Зря я затеял разговор с религиозным фанатиком.

                                              Что религиозного в признании практического удобства инструмента?

                                              А вот ваше нежелание допустить, что незнакомый вам инструмент может быть действительно удобен — это как-раз смахивает на религиозность.
                                        +2
                                        Что вы понимаете под «нормальной работой с СКВ» и почему она вдруг страдает из-за выравнивания?

                                        Во всех инструментах, с которыми я работаю изменение пробелов можно игнорировать, если для вас это так критично — но лично у меня из-за этого никогда проблем не возникало: gerrit по умолчанию выделяет тёмно-зелёным изменения «внутри строки» и если комментарии немного сдвинулись, то это сложно не заметить: все изменения показывают только пробелы.

                                        Вот git blame — да, тут это может помешать, но, как бы опцию -w никто пока не отменял.

                                        Какую-такую деятельность с СКВ вы разводите, что она стоит того, чтобы вдвое увеличить количество строк ухудшив притом ещё и читабельность? Просто интересно — я могу поверить что существует такой код, где это может быть критично, но как-то за много лет никогда с таким не сталкивался…

                                        P.S. А настройки форматирования как раз не субъективны, а впроне объективны: что gofmt сделает — то и будет. Тут нет места разговорам и переливанию из пустого в порожнее.
                    +2
                    Вообще статья неплохая, но первое предложение просто убивает. Это в Го-то простые правила? Вы их вообще читали? Или нет? Когда оба игрока пасуют подряд, игра заканчивается — уже в одном это правиле столько всего сконцентрировано: а если я не хочу пасовать? Что со мной сделают? И вообще — много вы знаете игр, которые имеют отдельную страницу Варианты правил XXX (в английской версии отдельной страницы нет, просто страница с описанием правил содержит целую кучу вариантов, правил подсчёта очков и прочего). Нифига себе «простые правила»…
                      0
                      Нет, к сожалению, я в игру не играл и с правилами не знаком. В докладе Пайк противоставил игру го шахматам, как разные подходы к настольным играм в восточной и западной культуре. Наврал? :)
                        +2
                        В этом месте — не наврал. Подходы — действительно разные. И язык Го тут похож на игру, да.

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

                        Дело в том, что если задаться целью не «выиграть», а «как можно дольше не проиграть», то можно сделать ещё сотни, тысячи ходов до того момента пока тебе станет совсем некуда ходить. Но, разумеется, нормального, человеческого, игрока в Го это не устраивает. Он хочет, чтобы игрок, которого обыграли, спасовал и сдался если у него нет «хороших ходов». А программе — пофигу: хороший ход или плохой, у неё есть только относительные понятия «лучший» ход или «худший».

                        То есть в Шахматах есть довольно сложные правила — но это всё. Если ты их знаешь — можешь играть хоть с чемпионом. Проиграешь, конечно, но играть — можешь. А в игре Го есть небольшое количество просто выглядящих правил, но зная только их играть ты не можешь. Вернее можешь, но только сам с собой — хорошие игроки с тобой и разговаривать не станут.

                        То же самое и с языком: кроме формальных, выглядящих простыми, правил есть ещё «дзен Го», который, формально, правилами не является — но без которого нельзя сказать что вы умеете писать на Го. Нужно уметь не просто соблюдать формальные правила, а работать с вот этими постулатами и идиомами.
                          +1
                          Нужно уметь не просто соблюдать формальные правила, а работать с вот этими постулатами и идиомами.

                          Да, именно, об этом же и речь. Там еще Пайк говорит, что здорово, что Go создаёт вокруг себя коммьюнити людей, разделяющих определенные взгляды (его взгляды, хаха) на программирование в целом, на приоритеты и стратегии.
                            0
                            Ваша претензия, если я правильно понял, сводится к тому, что по правилам хорошего тона сдаваться надо когда понятно, что поражение неизбежно. Но это не правило игры, а всего лишь правило хорошего тона. Такое же правило есть и в шахматах и в любой другой игре. Есть множество примеров когда кто то сдавался раньше времени, а потом оказывалось, что есть очень хитрый ход который позволяет выиграть — такие примеры иногда встречаются на goproblems.
                              0
                              Ваша претензия, если я правильно понял, сводится к тому, что по правилам хорошего тона сдаваться надо когда понятно, что поражение неизбежно. Но это не правило игры, а всего лишь правило хорошего тона.
                              Да ну? Если вы откажетесь сдаваться до того момента, пока на поле не останется пустых мест размером более единицы (а до этого момента уж куда-нибудь но можно сделать ход), то с вами никто, совсем никто не захочет играть.

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

                              Есть множество примеров когда кто то сдавался раньше времени, а потом оказывалось, что есть очень хитрый ход который позволяет выиграть — такие примеры иногда встречаются на goproblems.
                              В шахматах так тоже бывает — речь не об этом. Возможность сдаться у противника есть во многих играх. В Го же нет возможности не сдаться.
                                0
                                В шахматах новичок может зевнуть ферзя на пятом ходу. Правила запрещают играть до мата? Нет. Вот новичок и продолжает делать ходы несмотря на то, что его противнику очевидно кто выиграет. Тоже самое в го.

                                Что значит «нет возможности не сдаться»? Типичная игра в го заканчивается двумя способами: кто то сдаётся (точно также как в шахматах) или оба играют до тех пора пока захваченные области не будут касаться друг друга. Если вы имеете ввиду, что второй случай равносилен первому, потому что непонятно можно ли в какой либо из территорий построить живую группу, то это не так: в большинстве случаев можно доказаться с математической строгостью, что такую группу построить нельзя, а в тех 1% случаев где это неочевидно, можно добавить пару камней и сразу станет очевидно.
                                  0
                                  Типичная игра в го заканчивается двумя способами: кто то сдаётся (точно также как в шахматах) или оба играют до тех пора пока захваченные области не будут касаться друг друга.
                                  И оба случая — это «сдача по собственному желанию».

                                  Если вы имеете ввиду, что второй случай равносилен первому, потому что непонятно можно ли в какой либо из территорий построить живую группу, то это не так: в большинстве случаев можно доказаться с математической строгостью, что такую группу построить нельзя, а в тех 1% случаев где это неочевидно, можно добавить пару камней и сразу станет очевидно.
                                  А вот здесь мы уже приходим к тому же, что и в статье: вместо того, чтобы дойти до состояния, когда человек вынужден пасовать (до сакраментальной фразы «вам мат»), вы доходите всего лишь до состояния где что-то можно сделать «с математической строгостью». Игра го никогда на практике не доходит до точки, где ни один из противников не может ходить. Никогда. Хотя правила этого и не запрещают.

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

                          а если я не хочу пасовать? Что со мной сделают?
                          Не хотите пасовать — делайте ход.
                            0
                            Правила простые в том плане, что для почти всех случаев они сводятся к двум правилам: повторять позицию нельзя и на доске остаются только те группы камней у которых есть свободы. Да, есть особо хитрые случаи которые большинство игроков ни разу в своей жизни не встретит, и для них есть куча разных интерпретаций (ну там правила Инга и т.п.), но это, имхо, не делает правила го сложными.
                              +1
                              Ага. Восточная такая «простота»: у нас есть пара фраз, которые, якобы, являются правилами и три талмуда, которые объясняют — как их нужно правильно интерпретировать. Все эти ко, суперко, боевое ко, беспокоящее ко — они откуда, как вы думаете, взялись? От излишней простоты и очевидности? А подсчёт очков с помощью коллегиального решения судей — это как? Это чтобы ещё проще игру сделать? Зашибись какая простая игра…
                                +1
                                И вправду, можно изучить все эти тонкости и скажем зашитить диссертацию на эту тему, а потом обнаружить, что ни разу в жизни это не пригодилось потому что рассматриваемые хитрые случаи возникают в одной игре на несколько миллионов. Более того, если я правильно помню, все эти сложности произошли из японского правила подсчёта очков: считаются только окружённые пустые клетки которые противник согласен не пытаться занимать. В китайских же правилах считаются также камни на доске, что позволяет в случае любых разногласий тупо захватить все вражеские камни на своей территории и сделать подсчёт очков очевидным. Вы на эту тему упомянули, что это может занять сотни или даже тысячи ходов. Это не так, потому что в типичной игре оба игрока имеют как правило территории по 40-50 клеток и максимум там можно поставить 20-30 камней, если уж сильно хочется тянуть резину.
                                  0
                                  Более того, если я правильно помню, все эти сложности произошли из японского правила подсчёта очков: считаются только окружённые пустые клетки которые противник согласен не пытаться занимать. В китайских же правилах считаются также камни на доске, что позволяет в случае любых разногласий тупо захватить все вражеские камни на своей территории и сделать подсчёт очков очевидным.
                                  Да, китайский Го намного проще, тут спору нет. Тут я даже, может быть, соглашусь, что игра имеет достаточно простые правила (хотя сама, конечно, не проста). По крайней мере сложностей в доигрывании нет и восхитительная ситуация, когда «игрок теряет очки от хода в свою территорию, поэтому не может сделать ход, делающий его группу безусловно живой, если разница очков после такого хода поменяется в пользу противника, поэтому он предпочтёт не делать ходов и доказывать, что его группа и так жива» не возникает.

                                  Это не так, потому что в типичной игре оба игрока имеют как правило территории по 40-50 клеток и максимум там можно поставить 20-30 камней, если уж сильно хочется тянуть резину.
                                  Это если вы «хотите ясности» вы можете туда поставить 20-30 камней :-) А вот если «тянуть резину», то туда начнёт ставить камни ваш противник — и он, разумеется, может довести дело до того, что вам придётся ставить камни на его территорию (иначе — да, вы снимите его камни, но территории-то больше останется у него), дальше всё это снимется с обоих сторой и пойдёт на второй круг, потом — на третий и так далее.
                            –1
                            Каким образом Go принуждает меня красиво обрабатывать ошибки?
                              0
                              Где написано, что Go вас принуждает?
                                0
                                В том то то и дело, что нигде не написано. У Go какие-то красивые постулаты и принципы, вот только сам язык им не соответствует.
                                  0
                                  Обоснуйте, пожалуйста. Почему вам кажется, что Go не соответствует своим же постулатам?
                              0
                              > Небольшое копирование лучше небольшой зависимости
                              > Как пример — функция IsPrint из пакета strconv

                              А я посмотрел исходники. Там написано, что это костыль из-за слабого линкера, а не из-за «небольшое копирование лучше небольшой зависимости». 40 строк кода (не учитывая тестов) без единого изменения это не «небольшое копирование», а индусский код.

                              Пруф:
                              >> 405 // TODO: IsPrint is a local implementation of unicode.IsPrint, verified by the tests
                              >> 406 // to give the same answer. It allows this package not to depend on unicode,
                              >> 407 // and therefore not pull in all the Unicode tables. If the linker were better
                              >> 408 // at tossing unused tables, we could get rid of this implementation.
                              >> 409 // That would be nice.

                              Ничего ведь не мешало вынести функцию в самостоятельный пакет, подключать его в нужных местах и избежать забот о совместимости двух функций.
                                –1
                                Тогда были бы заботы о совместимости пакетов, в го ведь нет их версионирования :-)
                                  –3
                                  Там написано, что это костыль из-за слабого линкера

                                  Там написано, что эту реализацию можно будет убрать, если линкер сможет убирать неиспользуемые таблицы. Но суть остается той же — небольшое копирование может быть выгодней дополнительной зависимости.
                                    +1
                                    > Там написано, что эту реализацию можно будет убрать, если линкер сможет убирать неиспользуемые таблицы
                                    В моём комментарии (в частности, цитата из quote.go) именно это и сказано. Для чего вы повторяете слова собеседника?

                                    Прошу прощения, но я не вижу выгоды в необходимости поддержки двух разных версий одной и той же функции (и, да, я смотрел исходный код и версии в пакете unicode).
                                      0
                                      Для чего вы повторяете слова собеседника?

                                      Я не повторяю слова, а более точно цитирую. Есть разница между «причина костыля» и «возможный способ упрощения кода в будущем».

                                      Прошу прощения, но я не вижу выгоды в необходимости поддержки двух разных версий одной и той же функции (и, да, я смотрел исходный код и версии в пакете unicode)

                                      Вы эту концепцию в принципе не понимаете или конкретно с примером в strconv она вам не нравится?
                                        +1
                                        > более точно цитирую
                                        Куда уж точнее кусочка, вырезанного из комментариев в исходнике? :)

                                        Автор не говорит о «возможном способе упрощения кода», автор прямо признаёт, что две реализации данной функции это следствие слабого линкера (и нежелания, судя по всему, создавать пакет с одной функцией внутри).

                                        > Вы эту концепцию в принципе не понимаете или конкретно с примером в strconv она вам не нравится?

                                        Скопировать строчку-три-пять ещё, возможно, пойму, но не всю же функцию в 40 строк. Тем более, позднее выяснилось, что это другая реализация функции IsPrint, и, соответственно, разработчикам необходимо [было написать и] поддерживать обе её версии.

                                        Спасибо за затраченное вами время, но я не вижу далее продуктивного обсуждения данной дискуссии.
                                          0
                                          Спасибо за затраченное вами время, но я не вижу далее продуктивного обсуждения данной дискуссии.

                                          Пожалуйста.

                                          Автор не говорит о «возможном способе упрощения кода», автор прямо признаёт, что две реализации данной функции это следствие слабого линкера (и нежелания, судя по всему, создавать пакет с одной функцией внутри).

                                          Это одно и то же, и сути это не меняет — скопировать одну функцию может быть проще и эффективнее, чем тянуть новую зависимость, и причины этого могут быть совершенно разные. Никто же не говорит, что это всегда правильно, но там где это уместно — это нормально.
                                            –1
                                            Т.е. индусский говнокод — это нормально, даже по «уважительным» (это каким?) причинам? О_ok.
                                  –3
                                  К сожалению абсолютно пустой пост.

                                  Берем те же принципы. Убираем «Cgo is not Go», меняем «interface{} says nothing» на «void * says nothing» и получаем вполне корректный набор «постулатов» для C.
                                  С такими же минимальными изменениями можно натянуть на любой язык.

                                    –1
                                    Ну вы переборщили слегка. «Каналы оркестрируют...» — тоже на С натянете? )

                                    Но в целом да, многие постулаты тут относятся не только к Go, а к программированию в целом. И в этом и сила (и критика особо зашарпленных хабровчан) Go, что он навязывает вам эти взгляды на программирование, формируя вокруг языка круг людей, разделяющих эти взгляды и культуру программирования. Пайк в этом докладе об этом упоминает в конце.
                                      –1
                                      А почему нет?
                                      Давным давно писал на сях и использовал тогда модный подход с очередями. Они у меня как раз каналами и назывались.
                                      Или вы думаете что каналы в Go настолько уникальны, что никто не догадался похожую сущность придумать в других языках? Просто в других языках это делается на уровне библиотек, а не языковых конструкций.
                                        0
                                        Нет, я так не думаю, и более-менее знаком с реализациями подходов CSP в других языках. Но если вы всё еще сопротивляетесь, могу дальше возвразить — постулат «Gofmt's style is no one's favorite, yet gofmt is everyone's favorite» тоже на «С и любые языки» не натянешь :)
                                          –3
                                          Да, его забыл упомянуть. Но сути это не меняет, от 70% до 90% написанного верно для любого языка, не только Go. Называть это «постулатами Go» — лишь попытка приравнять Go и современные языки. Хотя Go откровенно отстает. Большое количество неформальных правил как раз этому подтверждение.
                                            0
                                            И про пакет unsafe забыли, и про syscall, ага.

                                            от 70% до 90% написанного верно для любого языка

                                            Большое количество неформальных правил как раз этому подтверждение.

                                            Вы же только что написали, что 90% написанного верно для любого языка, а строчкой ниже этим же пытаетесь «доказать», что Go отстаёт от ваших любимых языков.
                                              –3
                                              Для любого языка верно около 70% «постулатов» с синтаксическими отличиями. Оставшиеся описывают слабость языка. Например у C и Go общих «постулатов» гораздо больше, чем у C# и Go. Очевидно, что Go — низкоуровневый язык.

                                              В C# например нет проблем с interface{}, рефлексией и обработкой ошибок, потому что в языке есть generic, dynamic и Exception. У языков с significant whitespace нет потребности в fmt и нет холиваров по поводу правильной расстановки скобочек. У C++ нет проблем с подключением еще одной библиотеки, компилятор выкинет из бинарника все лишнее. «Пустые» значения во многих языках отсутствуют, конструктор при необходимости всегда вызывается.

                                              Фактически «постулаты» это обратная сторона проблем языка.
                                                +3
                                                В C# например нет проблем с interface{}, рефлексией и обработкой ошибок, потому что в языке есть generic, dynamic и Exception. У языков с significant whitespace нет потребности в fmt и нет холиваров по поводу правильной расстановки скобочек. У C++ нет проблем с подключением еще одной библиотеки, компилятор выкинет из бинарника все лишнее. «Пустые» значения во многих языках отсутствуют, конструктор при необходимости всегда вызывается.
                                                Давненько я такого не видел. То есть я видел случаи когда люди искренне заблуждались… но чтобы настолько…

                                                И ведь смысла писать длинные посты нет: в вашем мире нет ни PEP 008, ни других style guideов и разных beautifierов, никто не борется с мегабайтами кода которые подтягиваются из-за libICU и вообще всё в мире зашибись, а если у кого-то, кто пользует языки, отличные от Go, наблюдаются проблемы — ну так это из-за того, что у него карма плохая (пользователи Go, разумеется, страдают от выбора языка, с ними всё полнятно).

                                                Вот только скажите: вы профессиональный тролль или вы действительно верите в ту чушь, что тут написали?
                                                  –1
                                                  Вы как-то извратили мою мысль. Я сказал что постулаты — суть недостатки Go. Собственно любые «правила», «гайды» которые не поддерживаются компилятором — признак слабости языка\компилятора.

                                                  Я вовсе не говорил, что другие языки идеальны, куча недостатков есть у питона, C, С++, Java и C#. Это вовсе не значит что Go от этого стал хорош.
                                                    +1
                                                    Мне кажется вы, намеренно или не очень, путаете мысль «design patterns are bug reports for your language» и эти постулаты.

                                                    Эти proverbs — это же о другом. Никто не говорит «делайте вот только так, несмотря на то что компилятор вам позволяет делать иначе». Как раз наоборот, некоторые из этих постулатов борятся с навязанными ранее «паттернами», вроде раздутых интерфейсов или «единого верного способа» писать конкурентные программы.
                                                      –3
                                                      Эти proverbs — это же о другом.

                                                      Если внимательно посмотреть, то в спсике есть proverbs трех типов:
                                                      1) Общепрограммистские истины (конкурентность — не параллелизм, продумывайте все, пишите документацию для пользователей)
                                                      2) Оправдание ошибок дизайна (Рефлексия непонятна, Ошибки это значения)
                                                      3) Паттерны, описанные общими словами (мьютексы, share by communicating, пустые значения, интерфейсы с одним методом, использование fmt итд)

                                                      Последние две категории являются отражением это недостатков языка. Некоторые недостатки оправданы низким уровнем языка, другие появились просто потому что такое взбрело в голову авторам.
                                                        +2
                                                        Последние две категории являются отражением это недостатков языка.

                                                        С чего вы это взяли?
                                                          0
                                                          Ошибки дизайна очевидно являются недостатками, надеюсь с этим вы не будете спорить.

                                                          Почему паттерны являются недостатками попробую объяснить.
                                                          Например вы говорите что есть постулат вроде, «делать X, чтобы получить результат Y».
                                                          Это означает, что есть несколько способов сделать Y, но авторы языка считают идеологически правильным способом X.
                                                          Тогда зачем оставили другие способы? Причины могут быть разные, но обычно совместимость и быстродействие.
                                                          Если основная причина наличия двух (правильного и неочень) сделать одно и то же — совместимость, то почему не сделали флаг компилятора, который включает режим совместимости.
                                                          Если основная причина — быстродействие, то почему вообще авторы рекомендуют медленный путь, как «идеологически правильный»? Не поработали над быстродействием или есть расхождения между желаемым уровнем абстракции и фактическим?

                                                          Так можно разобрать любой «постулат», «паттерн» и много чего еще, как это не назови. В большинстве случаев найдешь недостаток в дизайне языка или компиляторе.
                                                            +1
                                                            Ошибки дизайна очевидно являются недостатками, надеюсь с этим вы не будете спорить.

                                                            Не буду, но прежде, чем что-то называть «ошибкой дизайна», нужно очень хорошо разобраться в теме и хорошо аргументировать. Что именно вы считаете в Go ошибкой дизайна?

                                                            Почему паттерны являются недостатками попробую объяснить.

                                                            Всё таки я верно угадал — вы путаете эти «постулаты» с паттернами.

                                    0
                                    Долго думал над первой фразой «Don't communicate by sharing memory, share memory by communicating.» и тому чему же она соотвествует в го. Озарение не пришло. Наверно моего хилого 1-го дана для этого мало?
                                      0
                                      Совсем никаких идей?
                                        0
                                        В этой фразе вроде как есть мутный намёк на территории и вроде как обмен (?) ими, но этом мне не сильно помогает.
                                          0
                                          Есть «классический» способ синхронизации работы с данными из нескольких потоков — через разделяемую память, там используются «классические» примитивы — мьютексы и семафоры. Это «communicate by sharing memory».
                                          В Go же есть более мощный способ строить разнообразные архитектуры программ, в которых много «тредов» — с помощью каналов, select-а и goroutin. Там не нужны мьютексы, потому что передача объекта по каналу — тождественно передаче владения. Это «share memory by communicating».
                                            0
                                            Это всё понятно, но вопрос был не о том. В статье написано, что «постулаты несут глубинный смысл для тех, кто знаком с игрой го.» Ну вот он я — знаком с этой игрой на уровне хилого первого дана, но никакого глубинного смысла в этих фразах не вижу.
                                              0
                                              В том абзаце речь идёт о книжке с постулатами об игре го. В статье — с постулатами о языке Go.
                                              Прокачивайте свой дан внимательности значит )

                                    Only users with full accounts can post comments. Log in, please.