В игре 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

Видео:

Комментарии (77)


  1. creker
    04.12.2015 12:27
    +9

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

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


    1. divan0
      04.12.2015 15:39
      -7

      А то стыдно за авторов — так кичатся дизайном языка, а документацию писать не умеют.

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


  1. vintage
    04.12.2015 14:25
    +3

    > Не общайтесь разделением памяти. Разделяйте память через общение.
    > Каналы — оркестрируют, мьютексы — сериализируют

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

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

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

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

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

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

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

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

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

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

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


    1. divan0
      04.12.2015 15:36

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

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

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

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

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

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

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

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


      1. vintage
        04.12.2015 17:37

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

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

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

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

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

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

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

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

        Жду статью про essential complexity рефлексии :-)


        1. mibori
          04.12.2015 18:38

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

          P. S.: может не понял, что вы в эти два понятия вкладываете.


          1. vintage
            05.12.2015 06:53
            -1

            1. Может быть множество равных интерфейсов с разными именами, вы не можете отличить io.Reader от my.Reader если в них объявлены одинаковые сигнатуры
            2. Есть рекомендация минимизировать число сигнатур вплоть до одного метода


            1. taliban
              09.12.2015 14:05

              Зачем мне отличать io.Reader от my.Reader, если мне нужно всего то совершить некое действие? Мне важно чтоб обьект поддерживал это действие, кто он мне глубоко не важно и не нужно их идентифицировать. В го это прекрасно работает.


              1. vintage
                09.12.2015 15:52
                +1

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


                1. taliban
                  09.12.2015 16:01

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


                  1. khim
                    09.12.2015 16:37
                    +3

                    По поему вы вообще говорите о разном. vintage говорит о том, что в языках C# и Java интерфейс — это не просто множество функций, которые могут быть реализованы для того или иного объекта, но ещё и «метка»: да, этот объект действительно пригоден для использования в определённом качестве. Интерфейс Cloneable вообще ни одного метода не содержит, что не делает его бессмысленным!

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

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

                    Это обозначает, по большому счёту, что для «генетического программирования» (в программе объединяются куски со StackOverflow в случайной последовательности пока не начинают проходить тесты, после чего код отправляется в production) язык Go подходит не так хорошо, как Java. Я вообще не уверен, что поддержка подобного стиля программирования — то, к чему стоит стремиться, но то, что Go для него не подходит — правда, тут как бы особо и спорить не о чем.


                    1. taliban
                      09.12.2015 17:11

                      Да, я это и имел ввиду, сам пишу на PHP и там в интерфейсы вкладывают то же что и vintage имеет ввиду, по интерфейсу можно так же идентифицировать прибывший обьект, поэтому я такое поведение знаю хорошо. с другой стороны и понимаю почему в го изменили саму сущность интерфейсов, для него такой тип не подходит. Может я просто не так выразился :)


                  1. vintage
                    09.12.2015 22:03

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

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


        1. divan0
          04.12.2015 18:48
          +2

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

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

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

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

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

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


          1. vintage
            05.12.2015 12:31

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

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

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


            1. divan0
              05.12.2015 15:19
              +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.


              1. vintage
                05.12.2015 17:56
                -2

                В таком случае это никакие не постулаты. И вообще всю статью можно было бы свести к «думай головой» и не морочить голову протекающими принципами.

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

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


                1. divan0
                  05.12.2015 18:07
                  +2

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

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


                  1. vintage
                    05.12.2015 20:49
                    -2

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


                    1. divan0
                      05.12.2015 20:54
                      +2

                      Так и знал, что вам первый пример кода более близок.


                1. bo0rsh201
                  06.12.2015 11:19
                  +1

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


              1. 05.12.2015 22:24

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


                1. divan0
                  05.12.2015 22:35

                  Это правда, но это на практике такая мелочь по сравнению с тем ужасом, который случается с кодом, когда разные программисты с разными предпочтениями меняют код в течении нескольких лет. Кстати, бывший коллега, когда ещё не писал на Go, но активно пытался найти изъяны — тоже этот довод использовал. После года реальной работы с Go этот «изъян» ни разу не дал о себе знать и не составил проблемы, зато теперь понимает, что код, всегда аккуратно выглядящий благодаря go fmt — это бесценно.


                  1. 05.12.2015 23:30

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

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


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

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

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

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


                    1. divan0
                      05.12.2015 23:37

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

                      Я не вижу никаких сложностей так писать код, если это настолько критичная для вашей работы вещь, что вы готовы отказаться от такого удобного инструмента, как go fmt.


                      1. 05.12.2015 23:50

                        Субъективные настройки форматирования для вас настолько критичная вещь, что вы готовы отказаться от нормальной работы с СКВ?


                        1. divan0
                          06.12.2015 00:23

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


                          1. 06.12.2015 02:04
                            -1

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

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

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

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


                            1. divan0
                              06.12.2015 12:14

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

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

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

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

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

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


                              1. 06.12.2015 12:22
                                -1

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

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

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

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


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


                                1. divan0
                                  06.12.2015 12:30
                                  +1

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

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

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


                        1. khim
                          06.12.2015 00:31
                          +2

                          Что вы понимаете под «нормальной работой с СКВ» и почему она вдруг страдает из-за выравнивания?

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

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

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

                          P.S. А настройки форматирования как раз не субъективны, а впроне объективны: что gofmt сделает — то и будет. Тут нет места разговорам и переливанию из пустого в порожнее.


  1. khim
    04.12.2015 23:51
    +2

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


    1. divan0
      04.12.2015 23:59

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


      1. khim
        05.12.2015 15:06
        +2

        В этом месте — не наврал. Подходы — действительно разные. И язык Го тут похож на игру, да.

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

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

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

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


        1. divan0
          05.12.2015 15:22
          +1

          Нужно уметь не просто соблюдать формальные правила, а работать с вот этими постулатами и идиомами.

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


        1. ankh1989
          06.12.2015 03:03

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


          1. khim
            06.12.2015 04:09

            Ваша претензия, если я правильно понял, сводится к тому, что по правилам хорошего тона сдаваться надо когда понятно, что поражение неизбежно. Но это не правило игры, а всего лишь правило хорошего тона.
            Да ну? Если вы откажетесь сдаваться до того момента, пока на поле не останется пустых мест размером более единицы (а до этого момента уж куда-нибудь но можно сделать ход), то с вами никто, совсем никто не захочет играть.

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

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


            1. ankh1989
              06.12.2015 04:50

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

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


              1. khim
                06.12.2015 11:59

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

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

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


    1. stepik777
      05.12.2015 00:19

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

      а если я не хочу пасовать? Что со мной сделают?
      Не хотите пасовать — делайте ход.


    1. ankh1989
      06.12.2015 02:57

      Правила простые в том плане, что для почти всех случаев они сводятся к двум правилам: повторять позицию нельзя и на доске остаются только те группы камней у которых есть свободы. Да, есть особо хитрые случаи которые большинство игроков ни разу в своей жизни не встретит, и для них есть куча разных интерпретаций (ну там правила Инга и т.п.), но это, имхо, не делает правила го сложными.


      1. khim
        06.12.2015 04:19
        +1

        Ага. Восточная такая «простота»: у нас есть пара фраз, которые, якобы, являются правилами и три талмуда, которые объясняют — как их нужно правильно интерпретировать. Все эти ко, суперко, боевое ко, беспокоящее ко — они откуда, как вы думаете, взялись? От излишней простоты и очевидности? А подсчёт очков с помощью коллегиального решения судей — это как? Это чтобы ещё проще игру сделать? Зашибись какая простая игра…


        1. ankh1989
          06.12.2015 05:00
          +1

          И вправду, можно изучить все эти тонкости и скажем зашитить диссертацию на эту тему, а потом обнаружить, что ни разу в жизни это не пригодилось потому что рассматриваемые хитрые случаи возникают в одной игре на несколько миллионов. Более того, если я правильно помню, все эти сложности произошли из японского правила подсчёта очков: считаются только окружённые пустые клетки которые противник согласен не пытаться занимать. В китайских же правилах считаются также камни на доске, что позволяет в случае любых разногласий тупо захватить все вражеские камни на своей территории и сделать подсчёт очков очевидным. Вы на эту тему упомянули, что это может занять сотни или даже тысячи ходов. Это не так, потому что в типичной игре оба игрока имеют как правило территории по 40-50 клеток и максимум там можно поставить 20-30 камней, если уж сильно хочется тянуть резину.


          1. khim
            06.12.2015 12:09

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

            Это не так, потому что в типичной игре оба игрока имеют как правило территории по 40-50 клеток и максимум там можно поставить 20-30 камней, если уж сильно хочется тянуть резину.
            Это если вы «хотите ясности» вы можете туда поставить 20-30 камней :-) А вот если «тянуть резину», то туда начнёт ставить камни ваш противник — и он, разумеется, может довести дело до того, что вам придётся ставить камни на его территорию (иначе — да, вы снимите его камни, но территории-то больше останется у него), дальше всё это снимется с обоих сторой и пойдёт на второй круг, потом — на третий и так далее.


  1. defuz
    05.12.2015 07:34
    -1

    Каким образом Go принуждает меня красиво обрабатывать ошибки?


    1. divan0
      05.12.2015 15:03

      Где написано, что Go вас принуждает?


      1. defuz
        06.12.2015 13:36

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


        1. divan0
          06.12.2015 13:40

          Обоснуйте, пожалуйста. Почему вам кажется, что Go не соответствует своим же постулатам?


  1. bohdan4ik
    05.12.2015 11:55

    > Небольшое копирование лучше небольшой зависимости
    > Как пример — функция 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. vintage
      05.12.2015 13:58
      -1

      Тогда были бы заботы о совместимости пакетов, в го ведь нет их версионирования :-)


    1. divan0
      05.12.2015 15:12
      -3

      Там написано, что это костыль из-за слабого линкера

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


      1. bohdan4ik
        05.12.2015 16:45
        +1

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

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


        1. divan0
          05.12.2015 16:50

          Для чего вы повторяете слова собеседника?

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

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

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


          1. bohdan4ik
            05.12.2015 22:14
            +1

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

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

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

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

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


            1. divan0
              05.12.2015 22:30

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

              Пожалуйста.

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

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


              1. JC_Piligrim
                08.12.2015 09:48
                -1

                Т.е. индусский говнокод — это нормально, даже по «уважительным» (это каким?) причинам? О_ok.


  1. gandjustas
    05.12.2015 16:23
    -3

    К сожалению абсолютно пустой пост.

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


    1. divan0
      05.12.2015 16:29
      -1

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

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


      1. gandjustas
        05.12.2015 16:33
        -1

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


        1. divan0
          05.12.2015 16:47

          Нет, я так не думаю, и более-менее знаком с реализациями подходов CSP в других языках. Но если вы всё еще сопротивляетесь, могу дальше возвразить — постулат «Gofmt's style is no one's favorite, yet gofmt is everyone's favorite» тоже на «С и любые языки» не натянешь :)


          1. gandjustas
            05.12.2015 16:51
            -3

            Да, его забыл упомянуть. Но сути это не меняет, от 70% до 90% написанного верно для любого языка, не только Go. Называть это «постулатами Go» — лишь попытка приравнять Go и современные языки. Хотя Go откровенно отстает. Большое количество неформальных правил как раз этому подтверждение.


            1. divan0
              05.12.2015 17:10

              И про пакет unsafe забыли, и про syscall, ага.

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

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

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


              1. gandjustas
                05.12.2015 19:55
                -3

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

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

                Фактически «постулаты» это обратная сторона проблем языка.


                1. khim
                  05.12.2015 20:14
                  +3

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

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

                  Вот только скажите: вы профессиональный тролль или вы действительно верите в ту чушь, что тут написали?


                  1. gandjustas
                    05.12.2015 20:24
                    -1

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

                    Я вовсе не говорил, что другие языки идеальны, куча недостатков есть у питона, C, С++, Java и C#. Это вовсе не значит что Go от этого стал хорош.


                    1. divan0
                      05.12.2015 20:30
                      +1

                      Мне кажется вы, намеренно или не очень, путаете мысль «design patterns are bug reports for your language» и эти постулаты.

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


                      1. gandjustas
                        05.12.2015 20:43
                        -3

                        Эти proverbs — это же о другом.

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

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


                        1. divan0
                          05.12.2015 20:53
                          +2

                          Последние две категории являются отражением это недостатков языка.

                          С чего вы это взяли?


                          1. gandjustas
                            05.12.2015 21:16

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

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

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


                            1. divan0
                              05.12.2015 21:20
                              +1

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

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

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

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


  1. ankh1989
    08.12.2015 10:41

    Долго думал над первой фразой «Don't communicate by sharing memory, share memory by communicating.» и тому чему же она соотвествует в го. Озарение не пришло. Наверно моего хилого 1-го дана для этого мало?


    1. divan0
      08.12.2015 15:02

      Совсем никаких идей?


      1. ankh1989
        10.12.2015 08:09

        В этой фразе вроде как есть мутный намёк на территории и вроде как обмен (?) ими, но этом мне не сильно помогает.


        1. divan0
          10.12.2015 08:19

          Есть «классический» способ синхронизации работы с данными из нескольких потоков — через разделяемую память, там используются «классические» примитивы — мьютексы и семафоры. Это «communicate by sharing memory».
          В Go же есть более мощный способ строить разнообразные архитектуры программ, в которых много «тредов» — с помощью каналов, select-а и goroutin. Там не нужны мьютексы, потому что передача объекта по каналу — тождественно передаче владения. Это «share memory by communicating».


          1. ankh1989
            10.12.2015 10:54

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


            1. divan0
              10.12.2015 14:28

              В том абзаце речь идёт о книжке с постулатами об игре го. В статье — с постулатами о языке Go.
              Прокачивайте свой дан внимательности значит )