Перевод: Один год с Go

Original author: Andrew Thompson
  • Translation
Под катом — перевод статьи опытного разработчика о его опыте практического применения Go. Важно — мнение переводчика может не совпадать с мнением автора статьи.




Итак, прошел год с тех пор, как я начал использовать Go. Неделю назад я удалил его из production.

Я пишу этот пост, потому что в течение последнего года многие спрашивали меня о впечатлениях от работы с Go, и мне бы хотелось рассказать о нем несколько больше, чем это возможно в Twitter и IRC — пока воспоминания не выветрились у меня из памяти.

Итак, поговорим о том, почему я не считаю Go полезным инструментом:

Инструментарий


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

анализ покрытия


Строго говоря, утилита для анализа покрытия кода в Go — это хак. Она работает только с одним файлом за раз и делает это, вставляя в него примерно вот такой код:

GoCover.Count[n] = 1

Где n — это идентификатор позиции ветвления в файле. Ну а еще она вставляет в конец файла вот такую гигантскую структуру:

действительно гигантская
var GoCover = struct {
        Count     [7]uint32
        Pos       [3 * 7]uint32
        NumStmt   [7]uint16
} {
        Pos: [3 * 7]uint32{
                3, 4, 0xc0019, // [0]
                16, 16, 0x160005, // [1]
                5, 6, 0x1a0005, // [2]
                7, 8, 0x160005, // [3]
                9, 10, 0x170005, // [4]
                11, 12, 0x150005, // [5]
                13, 14, 0x160005, // [6]
        },
        NumStmt: [7]uint16{
                1, // 0
                1, // 1
                1, // 2
                1, // 3
                1, // 4
                1, // 5
                1, // 6
        },
}


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

анализ производительности


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

func (b *B) nsPerOp() int64 {
    if b.N <= 0 {
        return 0
    }
    return b.duration.Nanoseconds() / int64(b.N)
}

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

компилятор и go vet


Одна из обсуждаемых сильных сторон Go — это быстрая компиляция. Насколько я могу сказать, это частично достигается за счет того, что многие проверки, которые обычно делает компилятор просто пропускаются — они реализованы в go vet. Компилятор не проверяет проблемы с одинаковыми именами переменных в разных областях видимости или с некорректным форматом printf, все эти проверки реализованы в go vet. Более того, качество проверок ухудшается в новых версиях: в версии 1.3 не показывает проблемы, которые показывала версия 1.2.

go get


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

$GOPATH


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

Go race detector


Вот это — неплохая штука. Огорчает что оно вообще нужно. Ну и тот факт, что работает не на всех поддерживаемых платформах (FreeBSD, кто-нибудь?) и максимальное количество goroutine всего 8192. Более того, необходимо умудриться столкнуться с race condition — что довольно трудно, учитывая насколько race detector все замедляет.

Рантайм


Channels/mutexes


Каналы и мьютексы МЕДЛЕННЫЕ. Добавление синхронизации через мьютексы на production настолько снизило скорость работы, что лучшим решением стал запуск процесса под daemontools и его перезапуск в случае падения.

логи падений


Когда go падает, все без исключения goroutine отгружают свой стек вызова в stdout. Объем этой информации растет с ростом вашей программы. Более того, многие сообщения об ошибках косноязычно сформулированы, к примеру ‘evacuation not done in time’ или ‘freelist empty’. Создается впечатление что авторы этих сообщений задались целью максимизировать трафик к поисковому движку google, потому что в большинстве случаев это единственный способ понять что происходит.

интроспекция runtime



Не работает, на практике Go поддерживает в живых концепцию «отладка принтами». Можно использовать gdb, но не думаю что вы захотите это делать.

Язык


Я не получаю удовольствия от написания кода на Go. Я либо сражаюсь с ограниченной системой типов с кастами всего в interface{} либо занимаюсь копипастой кода который делает практически одно и то же для разных типов. Каждый раз, когда я добавляю новую функциональность это выливается в определение еще большего количества типов и допиливания кода для работы с ними. Чем это лучше использования C с адекватными указателями, или использования функционального кода со сложными типами?

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

Проблемы вызывает преобразование byte[] в string и работа с массивами/слайсами. Да, я понимаю для чего все это было сделано, но по моим ощущениям оно слишком низкоуровневое по отношению к остальному языку.

А еще есть [:],... с append. Посмотрите на это:

iv = append(iv, truncatedIv[:]...)

Этот код требует ручного контроля, потому что append в зависимости от размера массива либо добавит значения, либо сделает перевыделение памяти и вернет новый указатель. Здравствуй, старый добрый realloc.

стандартная библиотека


Часть стандартной библиотеки неплоха, особенно криптография, которая в лучшую сторону отличается от простой обертки над OpenSSL, которую вам предлагает большинство языков. Но документация и все что связано с интерфейсами… Мне часто приходится читать код реализации вместо документации, потому что последняя часто ограничивается бесполезным «имплементирует метод X».

Большие проблемы вызывает библиотека 'net'. В отличие от обычных сетевых библиотек, эта библиотека не позволяет менять параметры создаваемых сокетов. Хотите установить флаг IP_RECVPKTINFO? Используйте библиотеку 'syscall', которая является самой плохой оберткой над POSIX из всех, которые я видел. Нельзя даже получить файловый дескриптор созданного соединения, все приходится делать через 'syscall':

Скрытый текст
fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_DGRAM, 0)
if err != nil {
    rlog.Fatal("failed to create socket", err.Error())
}
rlog.Debug("socket fd is %d\n", fd)

err = syscall.SetsockoptInt(fd, syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1)
if err != nil {
    rlog.Fatal("unable to set IPV6_RECVPKTINFO", err.Error())
}

err = syscall.SetsockoptInt(fd, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 1)
if err != nil {
    rlog.Fatal("unable to set IPV6_V6ONLY", err.Error())
}

addr := new(syscall.SockaddrInet6)
addr.Port = UDPPort

rlog.Notice("UDP listen port is %d", addr.Port)

err = syscall.Bind(fd, addr)
if err != nil {
    rlog.Fatal("bind error ", err.Error())
}


А еще вы получите море удовольствия, получая и передавая byte[] при вызове 'syscall' функций. Создание и удаление C структур из Go — это просто какой-то заряд позитива.

Возможно, так сделано для использования сокетов только в polling сценариях? Я не знаю, но любая попытка сложного сетевого программирования приводит к необходимости писать ужасный и непортабельный код.

Выводы


Я не могу понять смысл Go. Если мне нужен системный язык, я использую C/D/Rust. Если мне нужен язык с хорошей поддержкой параллелизма, то я использую Erlang или Haskell. Единственное применение Go, которое я вижу — это утилиты командной строки, которые должны быть портабельны и не тянуть за собой зависимости. Я не думаю, что язык хорошо подходит для «долгоживущих» серверных задач. Возможно, он выглядит привлекательно для Ruby/Python/Java разработчиков, откуда, насколько я понимаю, и пришло большинство разработчиков на Go. Я также не исключаю, что Go станет «новой Java», учитывая легкость развертывания и репутацию языка. Если вы ищите более хорошую версию Ruby/Python/Java, возможно, Go вам подойдет — но я бы не рекомендовал останавливать свой поиск на этом языке. Хорошие языки программирования позволяют вам развиваться как программисту. LISP демонстрирует идею «код как данные», «C» обучает работе с компьютером на низком уровне, Ruby показывает работу с сообщениями и анонимными функциями, Erlang рассказывает про параллелизм и отказоустойчивость, Haskell демонстрирует настоящую систему типов и работу без побочных эффектов, Rust позволяет понять как разделять память для параллельно выполняемого кода. Но я не могу сказать, что научился чему-то, используя Go.
Ads

Comments 304

  • UFO just landed and posted this here
      +18
      Я не переводчик, добавлю от себя.

      Попробовал писать на Go несколько домашних поделок, на работе пишу на C#. Если вкратце, я пока так и не смог оценить преимуществ Go, кроме кросплатформенности:

      1. Нет удобных средств для разработчика, IDE со встроенным дебаггером под винду так и не нашёл. Пользуюсь плагином для Idea
      2. Каналы — удобно, но мне они нужны для параллельной обработки массивов данных. В C# это решается проще, Parallel.ForEach и вперёд
      3. Очень непривычно создавать свои ненужные структуры для простой сортировки в Go. И в целом, LINQ для работы с коллекциями в разы удобнее. При работе с Go сильно не хватает
      4. Зачастую, Go кажется слишком низкоуровневым, даже чрезмерно. В идеале, не хотел бы видеть в языке указатели без особой на то причины
      5. Использовал библиотеку написанную на C++ в Go. Не скажу, что очень удобно, а, например, valgrind и вовсе не работает с такими приложениями. Встроенный отладчик память, выделенную в C++ коде, разумеется, не видит. И как отлаживать утечки?


      В целом, язык интересный, но для себя достоинств я пока не увидел.
        +6
        Аналогично, в основном на работе пишу на C#, тогда как хобби C++\Qt\QML. И те же самые замечания! К LINQ очень быстро привыкаешь, к генерикам, к честным ссылкам, к нормальной работе со строками в конце концов (А то в Go это то ли функции из «bytes», то ли «strings», и непонятно, выстрелит ли это в плане локализации)! Хотя некоторые вещи вроде «go» и «defer» хороши.
          0
          Dim0FF, QtRoS go-linq пробовали?
            0
             From(students).
             Where(func (s T) (bool, error){
                        return s.(*Student).age >= 20, nil
                }).
            


            Я правильно понимаю, что (а) внутри Where используется делегат и (б) в этом делегате входной параметр приводится к нужному типу?
              0
              Import your []*Student.
              Find those over 20. Note T is an alias for interface{}. So we make type assertion to our input type.

              Да.
                0
                Мда. Боль и печаль.
                  0
                  Dim0FF RomanPyr lair Ну есть менее печальные варианты , хотя далеко и не идеальные.
                    0
                    Все равно же делегаты, да?
                      0
                      Нет — в gen используются конкретные типы, поэтому приводить ничего не нужно.
                        0
                        Я не спрашивал, есть ли приведение типов (я вижу, что нет), я говорю, что аргумент Where — делегат. Это ведь так?
                          0
                          А — является ли аргумент Where функтором(лямбдой, замыканием, функциональным обьектом — как хотите) — да является. Честно говоря сложно представить реализацию без функтора.
                            0
                              +1
                              Либо я чего-то не понимаю в C#, либо в
                              fruits.AsQueryable().Where(fruit => fruit.Length < 6);
                              


                              fruit => fruit.Length < 6
                              


                              Как раз та самая лямбда-функтор-предикат.
                                0
                                Зависит от того, что именно вы понимаете под лямбдой/функтором.

                                fruits.AsEnumerable().Where(fruit => fruit.Length < 6);
                                


                                Внутри Where — делегат (анонимная функция), которая будет скомпилирована в исполняемый код вместе со всем остальным кодом вокруг, и выполнена .net-рантаймом в момент итерации.

                                fruits.AsQueryable().Where(fruit => fruit.Length < 6);
                                


                                Внутри Whereвыражение (AST), которое в момент компиляции будет только построено, а вот в рантайме будет проанализировано и выполнено тем способом, который нужен провайдеру, лежащему под fruits. Например, преобразовано в предикат WHERE Length < 6, если провайдер поверх БД. Или в $filter=Length lt 6, если провайдер поверх OData.
                                  0
                                  Черная магия .Net (:

                                  Не знал про такое — но это свидетельствует скорее о умном компиляторе IL кода, нежели выразительности самого языка. Такие вот «макросы времени исполнения», причем подобная «магия» в коде далеко не всегда оправдана. Честно говоря после войн с Hibernate в яве, я очень осторожно отношусь к «умным выражениям». Да и AOT накладывает ограничения на такие вещи.

                                  Впрочем формально, это действительно вполне обычный предикат-функтор.

                                  П.С. На C# и .Net действительно очень много вкусных и интересных вещей. Но есть и проблемы — эталонная реализация работает только под Windows, поэтому если у вас Linux\*BSD то продвинуть использование шарпа нетривиально. Вторая этот тот факт, что даже если вам удалось продвинуть Mono — ваша реализация будет медленнее работать и может быть подвержена ошибка среды исполнения (тут был цикл статей о нем). Ну и наконец третье, что экосистема шарпа скуднее по сравнению с той же явой.
                                  Во вторых, Go и C# уж совсем разные сегменты рынка занимают. Откуда такой интерес?
                                    0
                                    Не знал про такое — но это свидетельствует скорее о умном компиляторе IL кода, нежели выразительности самого языка.

                                    Ну, как… Есть у меня самописный недоORM-фреймворк для плюсов, там тоже можно писать вещи типа (простите за куски кутей)
                                    struct Record
                                    {
                                        int m_id;
                                        QDateTime m_timestamp;
                                        QString m_name;
                                    };
                                    // ...
                                    Adapted<Record> queries;
                                    auto records = queries.SelectByFields (_1 <= yesterdayDate && _2 == thisName);
                                    

                                    Разворачивается тоже в какое-то там SQL-выражение, в точке SelectByFields проверяются типы (чтобы ненароком не было выражения со сравнением даты со строкой или int'ом), в рантайме никаких лямбд нет, и так далее.

                                    Адресация, к сожалению, позициональная, именованную с достаточно кратким синтаксисом (чтобы не писать &Record::m_timestamp <= yesterdayDate) я пока не придумал.

                                    ДженерикиТемплейты для реализации всего этого пригодились, да.

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

                                          Из этого кода Boost Spirit вспомнился.
                                            0
                                            Компилируется, гм, небыстро, да. Но и с этим можно бороться. Да и отладка достаточно проста, если напихать static_assert'ы в нужных местах. Конечно, концепты эти ассерты заменят. Потому и жду.

                                            Что печальнее — бинари серьёзно раздуваются в дебаг-билдах (и, как следствие, пострипанная debug-информация и dbg-пакеты во всяких там линуксах).

                                            Спирит прекрасен, конечно. Хаскелевский parsec/attoparsec-код можно переносить практически не думая.
                                      0
                                      Не знал про такое — но это свидетельствует скорее о умном компиляторе IL кода, нежели выразительности самого языка.

                                      Не, IL-компилятор здесь вообще ни при чем. Это чисто C#-ный трюк, когда стрелочная запись в зависимости от ожидаемого типа разворачивается либо в анонимный метод, либо в конструктор AST (очень грубо — в LambdaExpression(CompareExpresssion(MemberAccessExpression(ParameterExpression("fruit"),"Length"), LessThan, ConstExpression(6)))). А дальше это AST уже разворачивается исполняемым кодом.

                                      Это не макрос, это совсем другого рода развлечение, очень мощное, по-своему.
                0
                Спасибо, попробую.
                  +1
                  Не, ну это как раз-таки та вещь, которую тут почти единогласно осуждают — использовать привычные для одного языка подходы в другом, где они совсем «неродные».
                    0
                    вот именно.
                +3
                Вот смотрите, вы же в C# понимаете отличия struct от object? Где они располагаются, как передаются в качестве параметра? Также, думаю, вам вполне понятны значения модификаторов ref и out? А давайте добавим сюда еще unmanaged код, где можно проводить операции с указателями, stackallock и fixed. Получается что в C# тоже не все просто. Кому-то тоже это может не нравится, а кто-то настолько привык, что даже не замечает. Видимо дело в привычке.
                  +2
                  Каналы — удобно, но мне они нужны для параллельной обработки массивов данных. В C# это решается проще, Parallel.ForEach и вперёд

                  Каналы вместе с горутинами по-идее призваны избавиться от callback-hell, который присутствует в некоторых языках.
                    0
                    В C# от него защищают async/await, если я все правильно понимаю.
                      +1
                      На C# не пишу, почитал сейчас немного про acyns/await. Насколько успел разобраться, это все же разные подходы.
                      Го меня цепляет тем, что можно просто писать plain-код. Тот же async/await будет работать не с любой функцией, она должна это поддерживать, а в го можно любое действие дернуть через go… и оно не будет блокировать остальные потоки выполнения. Т.е., тут не асинхронная модель.
                      В совокупности с каналами и особенно с такой фичей как «select» это позволяет очень легко писать сложную логику управления кучей параллельных задач. Но за это мы платим тем, что нужно следить за потокобезопасностью кода, в го у нас нет гарантий, что в середине функции планировщик не переключится на выполнение другой функции.
                        +1
                        Есть.
                        «Планировщик, я закончил на пока, дай другим поработать в моей треде» горутина говорит либо явно (есть спец функция), либо делая блокирующую операцию (чтение из канала). Примечательно, что если совершается системный вызов, то горутина зависает вместе со всей тредой и планировщик вынужден либо ждать, либо родить еще одну треду. Такие пироги.
                        Очевидно, что рядом работают в других тредах другие горутины и они могут начать писать туда, куда пишем мы. Но единственный язык, где об этом не нужно думать, это Rust.
                          +1
                          > единственный язык, где об этом не нужно думать, это Rust.
                          Ну почему же. Есть Erlang, Haskell, Clojure, где об этом точно не надо думать.

                          А рантайм Erlang-а, например, достаточно умен, чтобы выполнять блокирующие системные вызовы на отдельном пуле тредов, что делает работу системы еще более предсказуемой.
                            +1
                            Дак вот как раз если горутина слишком долго тупит (это может быть и не системный вызов), то создается еще тред, в который запихиваются другие горутины. Вот тогда мы и получаем возможные проблемы с одновременной записью в map, например, если не учтем этого.
                            Вот довольно тупой пример, иллюстрирующий ситуацию. pastebin.com/jkH1Nvp2
                            $ go run check.go
                            Count 10000; 25.437204715 - 25.484347422
                            Count 20000; 25.437177393 - 25.605745478
                            End
                            

                            Как видим, горутины тут пересекаются по времени выполнения, хотя никаких блокирующих операций не делается.
                              0
                              В Go 1.5 GOMAXPROCS по дефолту ставится равным числу ядер, соответственно, горутины выполняются на нескольких тредах по умолчанию.
                              То есть, ваш пример не демонстрирует ничего, кроме стандартного поведения.
                                0
                                Я и хотел показать стандартное поведение, что у нас нет гарантии того, что в середину одной горутины не может врезаться другая, например в середине записи в map попытаться тоже получить доступ к этому мапу. Если мы об этом не позаботились.
                                  0
                                  А, ну ок, я не тот мессидж прочитал.

                                  BTW, в корректности вот этого тезиса

                                  > если горутина слишком долго тупит
                                  > (это может быть и не системный вызов), то
                                  > создается еще тред, в который запихиваются другие горутины

                                  я ощутимо сомневаюсь, но не настолько ориентируюсь в планировщике Go, чтобы уверенно отрицать.
                                0
                                Я писал о том, что горутину никто не остановит. В вашем примере ее так же никто не остановил. :) Вы просто запустили две горутины. То, что рядом может выполняться еще горутина и одновременно с нами использовать наши же ресурсы, мне казалось очевидным, о чем я и написал:
                                > Очевидно, что рядом работают в других тредах другие горутины и они могут начать писать туда, куда пишем мы.

                                > Вот тогда мы и получаем возможные проблемы с одновременной записью в map, например, если не учтем этого.
                                Я просто не представляю, как можно не учесть этого. Невнимательность? Да, но а как же иначе? Если язык будет это за нас учитывать (не методами разделения ресурсов аля Rust, а блокировками) то мы, возможно, получим потери в скорости, где нам бы этого не хотелось.
                                  0
                                  Да, я некорректно выразился насчет остановки. Но технически такое может произойти если два треда попадут на одно ядро. Их будет переключать планировщик ОС.
                                    0
                                    Да, это конечно так :)
                      0
                      Я считаю, что синтаксис и текущая реализация языка программирования — вторичны по отношению к экосистеме и сообществу. Где был javascript? А потом пришли ребята с V8, другие ребята с node.js — и все поменялось в течении пары лет. В дизайне самого языка есть спорные момент: GOROOT, отказ от классов, ручное управление контейнерами, контроль ошибок через возвращаемые значения — но все это сделано с определенными целями — серверная разработка «чтобы не текло и не падало». У меня нет большого практического опыта работы с Go. Что видел — работает быстро, но программисты жалуются что много ручной работы на низком уровне. Время покажет куда он будет развиваться и какое вокруг него сформируется сообщество.
                      • UFO just landed and posted this here
                          +3
                          Тут, по-моему, не угадаешь. Как показывает практика, небольшая группа энтузиастов может угорать по чему угодно, сообщество формируются слабо прогнозируемым способом.
                          +12
                          а чего поменялось то? Как была лапша с коллбеками и промисами, так она там же и осталась
                            0
                            В том-то и магия. Ничего по сути не поменялось — а популярность растет. И разработчики думают над способами борьбы с лапшой. Генераторы и async await вот сделали :)
                              +2
                              На самом деле, тут все достаточно просто объяснимо, по крайней мере, постфактум.
                              1. Случайно образовался JS в браузере. Пусть достаточно случайное явление, но язык не повернется назвать магическим.
                              2. Жесткая конкуренция за растущий пирог случайно привела к тому, что он оказался во всех современных браузерах. Вот это магия, на мой взгляд. Условия рынка сложились достаточно специфические, здесь было вариантов пока еще много. Дальше все строго предсказуемо.
                              3. Пирог веба вырос настолько, что браузеры стали использоваться почти всеми цивилизованными людьми чуть ли не каждый день. Оно и понятно: почти мгновенная коммуникация — лучшее изобретение человечества пока что.

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

                              Итак, JS везде и не содержит изъянов, делающих его использование невозможным. Чего ждать? Того, что мы сейчас имеем. Пока веб-платформа не упрется в свои фатальные недостатки, она будет расти в сторону еще большего распространения, улучшения скорости работы и развития инструментов разработки. В принципе, после анонса WASM у меня не хватает фантазии, что еще может выйти определяющего.
                              Разве что расширение набора инструкций ARM для более эффективной работы виртуальной машины JS, но сначала надо стандартизировать их как следует.

                              Так что, думаю, популярность растет просто потому что до сих пор не уперлась в потолок, но не просто так, а потому что JS-интерпретатор — самый распространенный на планете интерпретатор/компилятор.
                            +3
                            Для javascript особо альтернативы не было по-моему. И, увы, никто так и не создал адекватной альтернативы (а еще — лучше замены связки HTML+JS+CSS) и теперь приходится с этим жить.
                          +4
                          Хороший перевод. Но я еще ожидал немного Вашего мнения по теме, ибо его несоответствие с мнением автора особенно выделено перед переводом.
                            +39
                            Это дисклеймер, чтобы фанаты Go не слили переводчику карму.
                              +10
                              В целом да :). На Хабре не все читатели замечают что какая-то статья является переводом и начинает обращаться к переводчику как к автору. А у переводчика нет года практического опыта работы с Go
                            +8
                            Еще одна мелочь в Go, которая меня дико раздражает, — это отсутствие optional arguments. Ну ничего, подумал я, можно ведь выкрутиться через дефолтные значения. Но и они, кто бы мог подумать, не поддерживаются, приходится строить подпорки.

                              +3
                              Вы, наверное, догадываетесь, что их там нет намеренно — на практике, по мнению авторов Go, удобство от наличия одноименных функций с разными сигнатурами параметров оказывается сбивающем с толку и запутывающим программистов. Этот вопрос есть в FAQ: golang.org/doc/faq#overloading
                                +6
                                Я умею гуглить, спасибо.

                                Авторы могут считать как угодно. Я не собираюсь говорить им как они должны делать свой язык. просто меня раздражает отсутствие возможности сделать что-то в стиле
                                func f(n int := 0) {
                                    // pass
                                }
                                

                                вместо вот таких не сбивающих с толку программистов решений.

                                Особенно после распаковки аргументов в Python (*args, **kwargs), с которым Go часто сравнивают.
                                  –2
                                  Вы совершаете ту же ошибку, что и автор статьи — вы боретесь с языком. Вместо того, чтобы понять, как с его помощью решать проблему, вы пытаетесь понять, как с его помощью сделать так, как я привык в других языках.
                                  Не нужно делать из variadic parameters попытку симулировать argument overloading. Поймите, что решить задачу (реальную задачу, которую должна решать программа) можно сделать несколько иным способом, кроме как «найти любой ценой способ передавать дефолтные значения». И ценой вашего болезненного раздражительного «отвыкания» будет более ясный и читабельный для других код.
                                +1
                                Optional arguments можно реализовать через структуру с инициализацией с именованными полями.
                                +4
                                Пишу на питоне когда нет особых требований к скорости исполнения, или на D — когда они есть. Счастлив в обоих случаях. Попытка освоить Go окончилась неудачей по причине отсутствия удовольствния при написании кода.
                                  +4
                                  Пишу на го пол года, до этого где то год назад всё в нем не нравилось (первый подход )), но появился проект в котором нужно было написать сложную бизнес логику, работающую по крайней мере не медленно, и всё это за 4 месяца. На java писать не хотел, на Си не умел, нужен был язык который изучишь быстро, в итоге выбор пал на го, и я не разочарован. Как оказалось на го писать легко и приятно, есть возможности профилирования памяти и процессора, быстрая компиляция, стандартная библиотека которая охватывает почти всё. Среду разработки использую LiteIDE, выглядит страшновато, зато работает быстро и всё что нужно есть. Писать тесты на нем легко и приятно. Ну и то что он активно развивается и имеет отзывчивое сообщество это также на мой взгляд огромный плюс. Пока я работал над проектом они выпустили новую версию GC которая уменьшила задержки до неприлично малых значений. Проект в итогде в продакшене, будем смотреть :)
                                    0
                                    Я меня практический опыт работы с GO всего пару месяцев. Пока вообще далек от проблем в статье, и не факт, что когда-то они передо мной встанут. Сейчас пишу веб-приложение для одного сайта и в целом очень доволен.
                                    Отмечу плюсы:
                                    — язык очень простой
                                    — довольно строгие правила синтаксиса, я понимаю все чужие исходники и думаю другие легко будут понимать, что написал я
                                    — доступны исходники стандартных библиотек
                                    — компилируемость, отпадает потребность хранить исходники на сервере
                                    Из минусов:
                                    — не хватает оператора ( условие? выражение: выражение )
                                    — не такие большие сообщество и база знаний. Не всегда удается найти готовые решения или ответы.
                                      +3
                                      — не такие большие сообщество и база знаний. Не всегда удается найти готовые решения или ответы.

                                      Язык программирования Go
                                      –40
                                      перевод статьи опытного разработчика о его опыте практического применения Go.

                                      Итак, прошел год с тех пор, как я начал использовать Go.


                                      Н-да… о-о-о-огромный опыт… — 1 год попробовал Go.

                                      Статья — бред!
                                      … обиженной девки, надувшей губки: «я такая красивая, а он меня не любит...»
                                        +9
                                        А аргументы кроме ad hominem у вас есть?
                                          –30
                                          аргументы в том, что 1 год — это не тот опыт чтобы рот раскрывать?
                                            +20
                                            Во-первых, учитывая, что Go всего три года — это вполне ощутимый срок.
                                            Во-вторых, за год можно получить достаточное количество как положительных, так и отрицательных впечатлений о языке и инструментарии, которые и изложить в статье.

                                            Но это все не важно, потому что аргумент «один год — не тот опыт, чтобы» — это и есть аргумент ad hominem. В посте изложены вполне конкретные вещи; спорьте с ними, а не с личностью автора.
                                              –4
                                              Go всего три года — это вполне ощутимый срок.

                                              не 3, а 6
                                                +5
                                                Go 1 вышел в марте 2012. Но даже если шесть — это все равно не меняет остальной аргументации.
                                          –32
                                          Вань! Ты посмотри какие клоуны — рот хоть завязочки пришей!


                                          Н-да… сильно я разрушил единомыслие и согласие в таком дружном семействе…

                                          Ты глянь, как по минусам тыцкают! ;-)

                                            +4
                                            По вашему невозможно быть опытным разработчиком без опыта использования Go? И сколько лет должен проработать c Go человек, писавший скажем всю жизнь на Си, чтобы иметь право высказывать свое мнение?
                                              –19
                                              По вашему невозможно быть опытным разработчиком без опыта использования Go?


                                              … в WEB-программировании? ;-)
                                              … или в этом… в DevOps-се? ;-) ;-)

                                              Обсуждать вкус устриц хотелось бы с теми, кто их пробовал.

                                              (с) М.Жванецкий
                                                +3
                                                или в этом… в DevOps-се? ;-) ;-)
                                                Вот есть такие ребята. У них всё на Go написано, номады всякие с консулами. Логично, что люди, которые крутятся в этой кухне, пытаются пробовать Go, потому что авторы Go его для этого самого и позиционируют. Системный язык из Go не получился, остался пресловутый web и DevOps. Кто по вашему должен составлять мнение о Go в таком случае, бородатые системные программисты?
                                                  +3
                                                  Сама фраза «системный язык» имеет различные смыслы. Вот в этом видео Александреску, Матсакиса, Страуструпа и Пайка спрашивают как раз один из вопросов про то, что вы считаете «системным языком».

                                                  Поэтому, если уж дискутировать о позиционировании, давайте озвучим факт, что под этим термином разные люди понимают разные вещи. Кому-то кажется, что они должны писать собственные аллокаторы, а кому-то важно писать продуктивные программы для облаков.
                                                    0
                                                    Кстати в Go реально написать свой аллокатор, с помощью syscall.Mmap и unsafe.Pointer например.
                                                      –1
                                                      Под «системным языком» можно понимать что угодно, но есть чёткие определения, что такое «прикладное ПО» и «системное ПО». На Go пишут прикладное ПО.

                                                      Я к Go отношусь совершенно нейтрально, язык свою нишу нашёл, и его используют. Я просто не понимаю, что хотел сказать товарищ выше и что он понимает под вкусом устриц. Но ему, наверное, лучше знать с высоты его 40 лет опыта в программировании. :)
                                                        –5
                                                        Под «системным языком» можно понимать что угодно, но есть чёткие определения, что такое «прикладное ПО» и «системное ПО».


                                                        Нука, нука… Определение — в студию.
                                                        Желательно со ссылкой на авторитетный источник.
                                                          +1
                                                          Я понимаю, что за 40 лет можно всё забыть, в том числе всякие скучные определения, но как искать в гугле, я думаю, вы помните. Выжпрограммист.
                                                            0
                                                            Вы не правы. Вам выше привели ссылку на то, где авторы 4х системных языков объясняют, что определения размыты и подразумевают разные вещи.
                                                            Зачем писать «четкие определения», если они заведомо не четкие, и их нет, и даже ссылки на субъективные определения, справедливые для какой-то одной эпохи, вы не можете нагуглить?
                                                              +1
                                                              Хорошо, если вам не нравится слово «чёткие», пусть они будут просто «определениями». Вы о чем спорите вообще, что хотите сказать? В любую, так называемую эпоху были программы, которые обеспечивали работу других программ.

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

                                                              (если что, минус не мой :)
                                                      0
                                                      Я не защитник гоу, но все таки считаю что ваш аргумент про системный язык требует аргументации.
                                                        0
                                                        Я же написал, что «системный язык не получился». Эту мысль можно проследить из этого интервью: sourcegraph.com/blog/live/gophercon2015/123645585015
                                                        Q: You mentioned initially having the clear target of being a systems language was important. Is that still the target or has the target changed?

                                                        A: At this point, we really think of Go as a general purpose language. That’s also how people use it. It’s being used across the spectrum, and so that’s how we feel at this point.

                                                        Q: Most users of Go seem to be server-side. Do you think one way to make Go more mainstream is to attract more client-side developers.

                                                        A: The original design was not a standard general purpose language; it was a systems server-side programming language. There’s no ui package, for instance. Now that it’s general purpose, we would really like a ui package, but it’s a lot of work to come up with something that’s cross platform. We could use a lot of experts from the Go community here.
                                                        Создатели языка сами позиционируют его как язык общего назначения, на таких языках обычно не пытаются всерьёз писать драйверы устройств, ядра операционных систем или прошивки для микроконтроллеров, но для написания достаточно низкоуровневого server-side кода он вполне подходит.
                                                    +8
                                                    Должен проработать, пока не полюбит Go, очевидно же.
                                                      +1
                                                      Видимо сей комментатор посчитал, что о языке можно писать лишь после его забвения. Через пять-десять лет мы получим первое поколение опытных АЛГОЛ-программистов и пойдут первые реально хорошие рецензии от опытных разработчиков. К 2030 ждем хороших рецензий на Паскаль, а Java столь молода, что на ней априори пишут лишь юниоры.
                                                    +2
                                                    Я не считаю GoLang — инструментом для всего подряд, в нем есть полезные вещи как горутины и каналы, поэтому сетевые задачи на нем решать удобно, а в других задачах он уступает другим инструментам.
                                                      +2
                                                      Что такое «сетевые» задачи? Автор поста пишет, что невозможно изменить параметры создания сокета, не используя syscall — это вообще что хрень такая-то? Нафига тогда го, если есть С?
                                                      «Go нужен хорош для сетевого программирования» — мантра которую все повторяют, но видимо уже забыли, что это вообще значит.
                                                        0
                                                        Очевидно, имеется ввиду не столько «сетевое», сколько «многозадачное с долгими ожиданиями событий для продолжения задач», когда создавать по потоку на каждую задачу — дорого, а делать всё в один поток — медленно. Спасением тут является кооперативная многозадачность (горутины, гринлеты, волокна, легковесные потоки). Многие языки поддерживают её в той или иной мере: Go, NodeJS, Python, D, Rust, C# да в общем любой современный язык.
                                                          0
                                                          Очевидно, имеется ввиду не столько «сетевое», сколько «многозадачное с долгими ожиданиями событий для продолжения задач», когда создавать по потоку на каждую задачу — дорого, а делать всё в один поток — медленно.
                                                          Это само собой.

                                                          Многие языки поддерживают её в той или иной мере
                                                          Да, но не так хорошо: NodeJs, Python, D, Rust, C# — там либо async+await либо yield либо callback-hell. Хотя в Python есть gevent, но результат выходит гораздо медленнее чем на Go. Вот Erlang — конкурент, но он мне не очень нравится, может ещё какой-то язык подскажите? Вот Rust был бы не плох, но там нет микро-тредов либо с ними беда. Поэтому для меня решения на Go в качестве «сетевых тулзов» на первом месте, (для веба и тяжелых расчетов он уступает питону, с++ и другим).
                                                            –1
                                                            Не вижу принципиальной разницы между await+async, go+chan и yield+run. Во всех упомянутых языках кооперативная многозадачность реализуются примерно одинаково.

                                                            Кто бы сомневался, что Python медленнее Go.

                                                            Подсказать могу — D на голову лучше Go. Когда наиграетесь в гопесочнице — добро пожаловать во взрослую джизнь :-)

                                                            Насчёт легковесных потоков в Rust не знаю — он такой же как Go в том смысле, что дизайн крутится вокруг одной единственной фичи, а остальные не реализуются с отпиской «это сложно в реализации поэтому не нужно» (я про исключения, не говоря уж про лисповые условия).
                                                              0
                                                              Не вижу принципиальной разницы между
                                                              Разница есть, в await и yield, ф-ии и библиотеки разделяются на 2 типа, при этом есть проблемы вызова одних типов из других. В go только один тип, поэтому такой проблемы нет и не нужно городить «синтаксический мусор».

                                                              Подсказать могу — D на голову лучше Go.
                                                              В нем тот же yield, а С/С++ он не заменит из-за скорости (а если скорость не нужна тогда можно заюзать хоть питон).

                                                              дизайн крутится вокруг одной единственной фичи, а остальные не реализуются с отпиской «это сложно в реализации поэтому не нужно»
                                                              Согласен, но это совсем другая история :).
                                                                0
                                                                1. Один тип легко преобразуется в другой.
                                                                2. Далеко не во всех языка есть эта разница.

                                                                1. Там те же волокна, что и в Go и нету костыльных «генераторов».
                                                                2. С чего бы ему быть медленней, если он такой же компилируемый, с опциональным сборщиком мусора и кастомизируемыми аллокаторами памяти?

                                                                  0
                                                                  1. Один тип легко преобразуется в другой.
                                                                  Это не так, попробуйте преобразовать Django в async+await…
                                                                  Какие-то небольшие библиотеки ещё можно преобразовать, но кто потом их будет поддерживать?, и опять же — раздвоение на 2 типа.

                                                                  1. Там те же волокна
                                                                  Вот это уже получше, попробовал — не плохо. Но раздвоение сохраняется, например vibe.d дублирует функционал стандартной библиотеки. Хотя для мелких проектов это не страшно. Надо будет проверить на сколько fiber быстрее/медленнее чем корутины от го.

                                                                  2. С чего бы ему быть медленней,
                                                                  Где то на dlang сайте вычитал — они рекомендуют использовать C если нужна бо'льшая скорость, хотя судя по мелким тестам пользователей он почти не отстает от c/c++.

                                                                  Вообщем, язык интересный, только похоже комьюнити очень маленькое, проблема с докой и примерами, возможно попробую его на какой-нибудь мелкой задаче.
                                                                    +2
                                                                    > Это не так, попробуйте преобразовать Django в async+await…

                                                                    Беглое гугление: http://media.codysoyland.com/pdf/django-on-gevent.pdf

                                                                    > Но раздвоение сохраняется, например vibe.d дублирует функционал стандартной библиотеки.

                                                                    А он-то тут при чём?

                                                                    > Где то на dlang сайте вычитал — они рекомендуют использовать C если нужна бо'льшая скорость

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

                                                                    > Вообщем, язык интересный, только похоже комьюнити очень маленькое

                                                                    Ну да, его не пиарят на каждом углу как сабж.
                                                                      0
                                                                      Беглое гугление
                                                                      Это не то, не микро-треды, я специально написал «async+await», можете не гуглить, за это никто не возьмется.

                                                                      А он-то тут при чём?
                                                                      Я его попробовал в качестве асинхрононнго фреймворка работающего с сетью, дак вот он частично дублирует стандартную либу, про что я и говорил.
                                                                      Если не vibe.d то что использовать для асинхронной работы с сетью?
                                                                        0
                                                                        gevent — это те самые «микротреды», о которых шла речь в этой ветке http://www.gevent.org/
                                                                        Что именно вы вкладываете в async-await мне не ведомо.

                                                                        Там есть разные либы, но vibe.d наиболее богатая в этом плане. Это же хорошо, когда у вас есть выбор между несколькими реализациями одного функционала, конкуренция, все дела, разве нет? :-)
                                                                      0
                                                                      Основная проблема с D, которая я вижу — отсутствие продвижения языка каким-нибудь монстром. Из этой проблемы вытекают более мелкие, но не критичные: слабый выбор IDE, органиченный выбор сторонних библиотек и фреймворков,. Однако качество языка и стандартных библиотек продаёт само себя, поэтому надеюсь что в ближайшее время ситуация исправится.
                                                                        0
                                                                        Сделал docker для D lang, кто хочет попробовать, запускать так:
                                                                        > docker run -it lega911/dlang
                                                                        # dmd --version
                                                                      0
                                                                      > В go только один тип, поэтому такой проблемы нет и не нужно городить «синтаксический мусор».
                                                                      Судя по короткому экскурсу в std.concurrency D — тамошние файберы работают как горутины и Fiber.yield возвращает с любого уровня вложенности вызовов => синтаксический мусор не нужен.
                                                                        0
                                                                        Fiber.yield возвращает с любого уровня вложенности вызовов
                                                                        Кстати в этом есть плюс — мы контролируем когда нам переключится, значит для глобальных/общих объектов в пределах потока локи не нужны в отличие от Го.
                                                                          0
                                                                          И минус — вы должны четко понимать, кто за кем следует, дабы не допустить блокировки или лишнего ожидания корутин. По сути вы выполняете работу планировщика, только вручную. Более того, ваши коллеги должны быть крайне внимательны при работе с таким кодом — наличие незащищенного shared state не является потокобезопасным, но у вас возможна работа с ним из разных потоков управления, что вызывает вопросы. Лично я такое решение считаю не очень удачным, и крайне не устойчивым — есть большая вероятность отстрела ноги, а ловить такие баги потом крайне неприятно и долго.
                                                                            –2
                                                                            И минус — вы должны четко понимать, кто за кем следует
                                                                            Да там полно минусов, поэтому горутины из Го — это значимая фича.
                                                                              0
                                                                              В D состояние по умолчанию не разделяется между потоками. Правда реализация передачи сообщений между ними использует блокировки. Не знаю, почему не реализовали неблокирующую очередь сообщений.
                                                                                0
                                                                                Так в Go тоже же самое, просто эти yield-ы спрятаны внутрь операторов работы с каналами и код работы с сетевым i/o. Я же говорю, файберы из D _по сути_ идентичны горутинам.

                                                                                Там могут быть различия в реализации, но суть та же.
                                                                          +4
                                                                          > D на голову лучше Go
                                                                          Не, ну давайте все же будем честны — в плане concurrent рантайма и интеграции его с event loop D до Go еще расти и расти, а кто будет за это платить — неясно.
                                                                            0
                                                                            Ну я так понимаю Александреску лично возглавит. С шашкой и на белом коне.
                                                                              +1
                                                                              Что же в Go такого удивительного в рантайме и интеграции? Я вижу лишь небольшую разницу в синтаксисе.
                                                                                0
                                                                                Ничего удивительного там нет, однако уже есть годный multicore планировщик с work stealing и уже написан неплохой враппер для асинхронного i/o на горутинах.

                                                                                Повторюсь, для Go оно уже есть, для D — непонятно когда будет и будет ли. Вся разница в этом.
                                                                                  0
                                                                                  Давно уже есть: https://gist.github.com/nin-jin/5f6969cb9063b1977769#file-coroutine-d — полный эквивалент горутин. Можно даже синтаксис сделать такой же приятный.
                                                                                  В Go варианте вывод какой-то странный — по две итерации каждой горутиной. В D в один поток они просто чередуются (в примере — два).
                                                                                    0
                                                                                    Не буду спорить, с D я не могу так навскидку разобраться, как там рантайм устроен.
                                                                                      0
                                                                                      Честно говоря — тяжело читать, у D нет своего онлайн компилятора?

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

                                                                                      Я мельком глянул vibe.core.stream — как я понял, там для неблокирующей операции нужно опросить ОС сколько уже готово, вручную.
                                                                                        0
                                                                                        Внезапно нашёл: http://dpaste.dzfl.pl/

                                                                                        Ну, запустите writeln в отдельном потоке.

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

                                                                                        Разница такая — если одна горутина заблокируется (бесконечный цикл или блокирующее io), то D приложение встанет колом, когда в Го приложение будет работать, Mikanor про это отписался.
                                                                                          0
                                                                                          Горутины выполняются параллельно, когда это возможно по мнению планировщика. Отсюда некая недетерминированность I/O. В примере на D sleep выполняются асинхронно, но друг за другом, в том время как в го асинхронно, но параллельно.
                                                                                            0
                                                                                            В примере на D даже глобальные состояния разные. О чём вы?
                                                                                            0
                                                                                            Судя по цифрам — они либо в одном потоке, которого вполне хватает для таких задач, либо в разных, но разделяют одно состояние, что ещё хуже.

                                                                                            Что ж вы придираетесь-то к простому примеру? Если вы заблокируете основной поток, то у вас на любом языке приложение встанет колом. Поэтому реальные задачи запускаются только в воркерах.

                                                                                              0
                                                                                              Для интереса сделал набросок балансировщика на dlang + vibe.d, тут не весь функционал и он уже отстает от версии на го на ~15-20% (запускал их в одном потоке + 10 клиентов и 10 ворекров). Может там нужно что-то «подтюнить»?
                                                                                                0
                                                                                                Не очень понял что там происходит. Может целиком бенчмарк выложите, чтобы я его мог у себя погонять?
                                                                                                  0
                                                                                                  Ох, как руки дойдут, но обещать не буду. Надо будет упростить скрипты, просто сделать проксирование.
                                                                                                    0
                                                                                                    Начал делать скрипт и с dlang беда какая-то — не возможно получить точное время, нашел рецепт, но он дает расхождения в 10 сек и более. Куда копать?
                                                                                                      0
                                                                                                      Подозреваю дело в том, что там считается ещё и время вывода в консоль, лови пул-реквест.
                                                                                                        0
                                                                                                        С текущей версий тестов получились такие результаты:
                                                                                                        Dlang
                                                                                                        
                                                                                                        26572
                                                                                                        26607
                                                                                                        26678
                                                                                                        26678
                                                                                                        ...
                                                                                                        
                                                                                                        Go
                                                                                                        
                                                                                                        33764
                                                                                                        33292
                                                                                                        33787
                                                                                                        33403
                                                                                                        ...
                                                                                                        

                                                                                                        Го быстрее на 26%.
                                                                                                          0
                                                                                                          Какой компилятор для D использовался?
                                                                                                            0

                                                                                                            dmd, очевидно.

                                                                                                              0
                                                                                                              Значит тест не представляет из себя никакой ценности. Поскольку DMD сейчас концентрируется на поддержке новых фич, а не на производительности генерируемого кода.

                                                                                                              lega, повторите тест используя GDC или LDC?
                                                                              0
                                                                              А со скоростью как в этих сетевых задачах?
                                                                                0
                                                                                У меня есть балансировщик для rpc на python + zeromq и аналогичный на golang, дак вот версия на golang в 3-4 раза производительней (что не удивительно). Кроме этого, не прямые конкурентные решения на C/C++ и Erlang работают медленнее (в разы), хотя в первую очередь это связано с набором фич, и производительность языков тут не сравнить.

                                                                                Вполне возможно на С++ написать ещё более быструю версию, но возится с асинхронностью и процессами, что берет на себя GoLang из коробки, для меня не оправдано.
                                                                                  0
                                                                                  golang версия тоже через zeromq работает?
                                                                                    0
                                                                                    Нет, но основная логика приложения та же, (не думаю что ручная работа с сокетами и селектами в питоне даст больший профит чем через zmq).
                                                                                    0
                                                                                    , дак вот версия на golang в 3-4 раза производительней (что не удивительно)

                                                                                    Это очень удивительно, ищите ошибки в архитектуре rpc на python + zeromq, такого не может быть.
                                                                                      +2
                                                                                      такого не может быть.
                                                                                      Не может быть что питон медленнее чем golang? Я думаю это очевидно что питон медленнее. Вот код.
                                                                                        0
                                                                                        Питон медленнее Го, но не в три-четыре раз, плюс речь идет о сетевом приложении, где основные тормоза это ожидание готовности ввода/вывода. И если у вас похожая архитектура, во всяком случае и там, и там асинхронная обработка сетевых подключение, то 3-4 раза очень и очень сомнительно.

                                                                                        Готов забрать свои слова назад, если представите адекватные тесты.
                                                                                          0
                                                                                          Питон медленнее Го, но не в три-четыре раз
                                                                                          Да, не в три-четыре, а больше, если сравнивать скорость исполнения питон-байткода.
                                                                                          Например можете запустить у себя эти 2 цикла, у меня го выполняет в 100 раз быстрее. А в одном реальном проекте был расчет математики и я получил ускорение в 17 раз (и ещё больше при C++).
                                                                                          А вот исходники тех самых балансировщиков, py и го.

                                                                                          У Python'а много других достоинств, и Го там рядом не стоит. (Поэтому я на сервер-сайде использую Python, GoLang, C++ совместно для разных задач).
                                                                                            0
                                                                                            Пустые циклы очень хорошо оптимизируются компиляторами, удивляюсь что только в 100 раз :)
                                                                                            Математика да, операции с плавающими числами в питоне медленные. Математику в питоне или не считают или считают с использованием специализированных пакетов типа numpy, насколько я знаю.

                                                                                            Скажите сколько ядер на машине, где вы сравнивали Go и Python код вышеприведенный?
                                                                                              0
                                                                                              Пустые циклы очень хорошо оптимизируются компиляторами
                                                                                              Такие циклы обрезаются умными компиляторами, но это не тот случай.

                                                                                              Математику в питоне или не считают или считают с использованием специализированных пакетов типа numpy, насколько я знаю.
                                                                                              Да, питон достаточно быстрый для своих задач за счет того что многие модули написаны на C/C++.

                                                                                              Скажите сколько ядер на машине
                                                                                              2, но это не имеет значения для данного теста (Во всех тестах я делал с ограничением в одно ядро и без).
                                                                                                –2
                                                                                                но это не тот случай

                                                                                                Почему, очень похоже именно на этот случай.

                                                                                                Во всех тестах я делал с ограничением в одно ядро и без

                                                                                                А как вы добились того, что бы Go не форкался автоматом по числу ядер?
                                                                                                  0
                                                                                                  очень похоже именно на этот случай.
                                                                                                  Если бы цикл вырезался, то приложение не задерживалось бы на 0.4 сек (на 4 сек при увеличении цикла в х10 раз). Для уверенности можете какую-нибудь сложную математику протестировать.

                                                                                                  что бы Go не форкался автоматом по числу ядер?
                                                                                                  Это управляется с помощью GOMAXPROCS
                                                                                                    0
                                                                                                    Для уверенности можете какую-нибудь сложную математику протестировать.
                                                                                                    Математику не стоит, она очень плоха в питоне из коробки, просто делайте что-то в цикле, хотя бы просто инкременируйте переменную.

                                                                                                    Как тестите эти два приложения? Есть такая штука github.com/joshmarshall/tornadorpc
                                                                                                    было бы интересно сделать аналог на нем и посмотреть.
                                                                                            0
                                                                                            Погонял у себя примитивный тест lega (но с py версией с «while i < 1000000000»), Python вообще в 184 раза медленнее Go получился…
                                                                                              0
                                                                                              А вот это даже как-то странно.
                                                                                                0
                                                                                                Я как раз с while и гонял, написал же.
                                                                                                  0
                                                                                                  Сори, не внимательно прочитал сперва :-)
                                                                                                    0
                                                                                                    Причем, 184 раза это python2.7. На python3.4 разница вобще в 275 раз.
                                                                                                      0
                                                                                                      Можете, ради интереса, попробовать запустить на pypy, — не будет отставать* от golang, если не обгонит.
                                                                                                        0
                                                                                                        pypy медленнее Go в 14 раз…
                                                                                                          0
                                                                                                          Я чуть поправил py код:
                                                                                                          import time
                                                                                                          
                                                                                                          def main():
                                                                                                              i = 0
                                                                                                              while i < 1000000000:
                                                                                                                  i += 1
                                                                                                          
                                                                                                          start = time.time()
                                                                                                          main()
                                                                                                          finish = time.time()
                                                                                                          print(finish-start)
                                                                                                          


                                                                                                          pypy 2.2: 650ms
                                                                                                          golang: 405ms

                                                                                                          т.е. pypy получился медленнее на ~40%
                                                                                                            0
                                                                                                            Да, так уже лучше: у меня разница всего в два раза примерно (6.0 против 3.5).
                                                                                                              0
                                                                                                              Добавил в циклы суммирование всех значений i:
                                                                                                              go — 6сек
                                                                                                              pypy — 165сек

                                                                                                              Разница 27 раз. Ну я так не играю)
                                                                                                                0
                                                                                                                Возможно из за того, что в этом случае в Го используется long*, когда pypy думает что результат может выйти за 8 байт и переключается на «bigint», а он гораздо медленнее.
                                                                                                                  0
                                                                                                                  Скорее всего. Если не допустить выхода за пределы разница всего в полтора раза.
                                                                                                                  0
                                                                                                                  А я добавил D — он в 2 раза быстрее чем Go отработал.

                                                                                                                  https://gist.github.com/lega911/c4b627c3f17625f05d44#gistcomment-1595006
                                                                                                                    0
                                                                                                                    dub это уже скомпиленное? Может тогда и Go запускать уже скомпиленное?
                                                                                                                      0
                                                                                                                      dub — это пакетный менеджер. В данном случае, он устанавливает зависимости, компилирует, линкует и запускает.
                                                                                                                        0
                                                                                                                        Причём тут скомпилированное или нет, если замер делается во время исполнения?
                                                                                                        0
                                                                                                        Да вроде ожидаемо, на сложных задачах разрыв будет меньше (вон брокер сверху всего в 3-4 раза), а если будут сплошные вызовы расширений (numpy или математика на cext), то питон будет даже быстрее. Рассматривайте питон как медленный менеджер над быстрым С-кодом.
                                                                                                          0
                                                                                                          Я сравнивал Go с C++ на несложных алгоритмах на массивах и хешах — по скорости вообще почти нет разницы.
                                                                                                          Только в случаях совсем уж сложных вещей, которые хотят всяких -O3 -march и т.п.
                                                                                                          Но Go он для сетевых сервисов все таки, а не считать Пи.

                                                                                                          «всего в 3-4 раза» больше серверов надо…
                                                                                                            0
                                                                                                            Я на одной реальной, математической задаче получил х2 прирост на С, наверно за счет отсутствия GC и более быстрого map.
                                                                                                              0
                                                                                                              Но Go он для сетевых сервисов все таки, а не считать Пи.
                                                                                                              Вот с этим я согласен, я с этого тред начал.
                                                                                            +1
                                                                                            Один в один мои впечатления от ГО. Правда, год писать я на нём не осилил: ощущение борьбы с языком так и не ушло.
                                                                                            Добавлю так же, что система тэгов для полей структур — тоже очень странная. Выглядит как костылик подставленный опосля («О! А я ещё классную штуку вспомнил»). Соответственно, работа с xml и json заставляет периодически заниматься кодогенерацией, а не динамической генерацией структур.
                                                                                              –1
                                                                                              Каналы и мьютексы МЕДЛЕННЫЕ. Добавление синхронизации через мьютексы на production настолько снизило скорость работы, что лучшим решением стал запуск процесса под daemontools и его перезапуск в случае падения.

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

                                                                                              Медленные ли мьютексы Go? Не знаю, не проверял… но какой-то особенной тормознутости в глаза не бросается. Но это низкоуровневый механизм в Go, который — везде там над входом написано, разуй глаза — не рекомендуется использовать.
                                                                                                +1
                                                                                                Но она свободна от ошибок, в отличие от низкоуровневой модели.

                                                                                                От каких ошибок?
                                                                                                  –7
                                                                                                  От каких ошибок?

                                                                                                  От ваших ошибок… от кривых рук ;-)
                                                                                                    +9
                                                                                                    Ага, конечно. От кривых рук спасают иммутабельность(Haskell, Clojure), share nothing(Erlang) или move semantics(Rust, C++11+).
                                                                                                    В Go есть только соглашения и рекомендации, никакой реальной защиты они не предоставляют.
                                                                                                –7
                                                                                                Я не могу понять смысл Go. Если мне нужен системный язык, я использую C/D/Rust. Если мне нужен язык с хорошей поддержкой параллелизма, то я использую Erlang или Haskell.

                                                                                                Параллелизм и конкурентность — очень разные вещи, когда вы переходите к SMP и истинной многопроцессорности.
                                                                                                Параллелизм Erlang или Haskell — кажущийся… логический, если хотите. Эффективное распараллеливание функциональных языков на мультипроцессоры — это больше теоретические изыски, чем практические достижения.
                                                                                                Главная фишка Go — эффективное использование многопроцессорной среды за счёт лёгких goroutine.
                                                                                                Опыт (тестовые результаты) показывает, что они быстрее и эффективнее pthread_t языка C и POSIX.
                                                                                                Не говоря уже про Python и многие другие интерпретируемые языки, где параллельные ветви — это вообще только фикция, модель удобная для формализации и только… а реально они толкутся на одном процессоре только затрудняя выполнение.

                                                                                                  +6
                                                                                                  Опыт (тестовые результаты) показывает, что они быстрее и эффективнее pthread_t языка C и POSIX.

                                                                                                  Сильное утверждение. Покажите тестовые результаты, пожалуйста.
                                                                                                    +3
                                                                                                    Тесты сравнения горутин и pthread? Ну когда pthread можно будет запустить в одном процессе хотя бы сто тысяч штук, то можно будет сравнивать. А так это все-таки вещи под разные задачи, причем первые «внутри» работают как раз на вторых.
                                                                                                      0
                                                                                                      Если goroutine работает поверх posix thread, то по каким критетиям вы сравнивали их скорость и эффективность?
                                                                                                        0
                                                                                                        Их сейчас нельзя сравнивать по скорости. Я не понимаю, как Olej смог их сравнить именно в категории «быстрее и эффективнее».
                                                                                                        Сравнивать можно разве что в контексте удобства использования и потребления ресурсов каждой из сущностей.
                                                                                                          0
                                                                                                          А когда можно будет?
                                                                                                            +2
                                                                                                            Еще можно сравнить скорость переключения, но ежу понятно, выиграют зеленые треды, где нет трипов в ядро на переключение контекста, они для этого и придуманы.
                                                                                                        0
                                                                                                        Посмотрите silver searcher и platinum searcher. Идут ноздря в ноздрю с незначительным перевесом в пользу Go.
                                                                                                          0
                                                                                                          Спасибо за ссылки. Честно говоря, хотелось бы посмотреть на готовые результаты. Данный тред, безусловно, интересен, но на самостоятельную сборку и тестирование уйдёт слишком много времени.
                                                                                                            0
                                                                                                            В readme к platinum searcher есть результаты измерений автором. Простенькие правда, но тем не менее.
                                                                                                        +12
                                                                                                        вы мягко говоря не в курсе о чём пишете.

                                                                                                        Параллелизм у Erlang основан на акторах, т.е. легковесных именованных процессах, которые обмениваются сообщениями через анонимные каналы.

                                                                                                        У Go это анонимные корутины, общающиеся через именованные каналы.

                                                                                                        Масштабирование эрланга по ядрам — это реальность, причем на много лет более реальная, чем существует Go. Не пишите того, о чём не знаете.
                                                                                                          +2
                                                                                                          Что вы понимаете под словом «эффективность»? Вы его употребляете в разных контекстах несколько раз.

                                                                                                          Параллелизм и конкурентность, действительно, вещи не эквивалентные. Erlang, например, про конкуретность (но, вроде как, Go с ним соперничает в этом). И тут же можно сразу поговорить о том, как работает планировщик в Erlang и в Go. У первого он обеспечивает действительно настоящюю вытесняющую многозадачность, чётко отводя процессам лимит времени (если быть совсем точно, то лимит инструкций) и переключая процессы по достижению этого лимита или раньше (но не позже!). Это обеспечивает невероятную плавность планирования (в купе с механизмами work stealing и настраиваемыми стратегиями распределения работы по планировщикам). Да, ценой некоторой потери в производительности (всё-таки виртуальная машина), но ведь тут речь про регулирование конкуретного доступа к ресурсам, а не числодробление. Я когда год назад искал информацию по тому, как именно работает планировщик в Go, не нашёл ничего, кроме упоминания, что переключение осуществляется на вызовах в runtime. Понятно, что на компилируемом в native-код языке трудно сделать честную вытесняющую многозадачность лёгких потоков, но это так же ставит вопрос, где всё-таки concurrency сделана эффективнее.

                                                                                                          Что касается наброса про параллелизм в Haskell, опять же, без определения слова «эффективность» это можно было бы оставить без внимания. Но я просто немного понедоумеваю. Haskell компилируется ровно в тот же самый native-код, что и Go. Треды ОС под планировщиком там ровно такие же. И ровно так же он способен параллельно выполнять код (именно параллельно, до стадии, пока не доделаю, а не пока не попросят освободить ядро). Инструменты для анализа есть. Книга, как делать правильно тоже есть. Где мне этот параллелизм кажется и где отсутствие практических достижений, объясните, пожалуйста?
                                                                                                            +5
                                                                                                            Параллелизм Erlang или Haskell — кажущийся… логический, если хотите. Эффективное распараллеливание функциональных языков на мультипроцессоры — это больше теоретические изыски, чем практические достижения.

                                                                                                            Ну, расскажите мне про это, пожалуйста.
                                                                                                            0
                                                                                                            обычно не язык или технология решает, а платформа вокруг которой построен язык, взять тот же самый дельфи и си#
                                                                                                              –4
                                                                                                              если бы у го был бы хороший mvc фрпймворк или rad платформа все бы сразу побежали бы туда!
                                                                                                                –8
                                                                                                                это справедливо… но только с точки зрения того, кто ничего кроме Windows не видел ;-)
                                                                                                                  0
                                                                                                                  Так многие и побежали или у вас ест сомнения что гоу вырвался из рамок экзотического языка?
                                                                                                                  +4
                                                                                                                  Я либо сражаюсь с ограниченной системой типов с кастами всего в interface{} либо занимаюсь копипастой кода который делает практически одно и то же для разных типов.

                                                                                                                  Я вот пытаюсь понять, как язык, в котором надо делать такие манипуляции может стать новой Java.
                                                                                                                    –9
                                                                                                                    Я вот пытаюсь понять,

                                                                                                                    Ну и как? ;-)

                                                                                                                    как язык, в котором надо делать такие манипуляции может стать новой Java.

                                                                                                                    А почему и как (?!) компилируемый в машинный код язык может стать «новой Java», которая требует интерпретации байт-кода в JVM?
                                                                                                                      +1
                                                                                                                      Ну и как? ;-)

                                                                                                                      И пока не понимаю.
                                                                                                                      А почему и как (?!) компилируемый в машинный код язык может стать «новой Java», которая требует интерпретации байт-кода в JVM?

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

                                                                                                                      +5
                                                                                                                      В том-то и дело, что там не нужно делать такие манипуляции. Если человек все кастит в interface{}, значит он пытается перенести абсолютно чужие и крепко засевшие в голове паттерны туда, где они не нужны. Это печально, таких надо отсеивать на первом же собеседовании :)
                                                                                                                        +4
                                                                                                                        Я слышал в Go нет дженериков. Как тогда делать контейнеры наподобие листов? Чтобы при вытаскивании не приходилось кастить элементы к нужному типу.
                                                                                                                          0
                                                                                                                          Они нинужны же.
                                                                                                                            –5
                                                                                                                            Дженерики — это не только параметризированные контейнеры, и их важность для реальной разработки программистами из других языков сильно переоценена и приводит к тому, что дженерики используются по поводу и без.

                                                                                                                            Если вам действительно интересна тема, рекомендую вот этот обзор дискуссий о дженериках в Go: docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4/edit#heading=h.vuko0u3txoew
                                                                                                                              +1
                                                                                                                              Вот, я же говорил, дженерики нинужны.

                                                                                                                              BTW, https://gist.github.com/kachayev/21e7fe149bc5ae0bd878 — «Channels Are Not Enough or Why Pipelining Is Not That Easy», отличное чтиво, как раз по теме.
                                                                                                                                –2
                                                                                                                                Качаев — знатный кложурщик и Go-хейтер, да )
                                                                                                                                  +2
                                                                                                                                  Кложурщик — если что, это не ругательство :) Я с ним знаком лично, и человек даже на митапе про Go пытался всем навязывать Clojure и рассказывал, что Go и удобства в конкурентности, это не серебрянная пуля, потому что там нет иммутабельных структур, поэтому переходите на Clojure. :)
                                                                                                                                +2
                                                                                                                                Ну давайте хотя бы с контейнерами разберёмся. Как в Go сделать параметризированный контейнер?
                                                                                                                                  –2
                                                                                                                                  Да что ж там разбираться — храните interface{}, как в golang.org/pkg/container/list.

                                                                                                                                  С дженериками вопрос же о другом.
                                                                                                                                    +9
                                                                                                                                    В том-то и дело, что там не нужно делать такие манипуляции. Если человек все кастит в interface{}, значит он пытается перенести абсолютно чужие и крепко засевшие в голове паттерны туда, где они не нужны. Это печально, таких надо отсеивать на первом же собеседовании :)

                                                                                                                                    Мне показалось, или за полтора часа язык программирования Go действительно радикально изменился?
                                                                                                                                      –2
                                                                                                                                      А вы не отличаете «постоянно сражаюсь с ограниченной системой типов с кастами всего в interface{}» от «как написать параметризованный контейнер»?

                                                                                                                                      Я всё жду, пока вы дойдете до вопроса «А почему авторы Go считают, что в программировании есть что-то иное, кроме параметризованных контейнеров?». Или вы тоже каждый день пишете свои параметризованные контейнеры из года в год?
                                                                                                                                        +2
                                                                                                                                        Ну вроде речь сейчас идёт о параметризированных контейнерах. И, как я понял всё, что туда кладёшь надо кастить в interface{}, а потом обратно. И это следствие ограниченности системы типов.
                                                                                                                                          0
                                                                                                                                          Ну это вы о контейнерах, а я о шаблонах и паттернах которые человек не хочет или не может пересмотреть по мере того, как он пытается освоить новый язык. Начиная с того, что кастят в interface{} некоторые новички в массе других ситуацией, и заканчивая тем, что параметризация очень часто используется там, где она 100 лет не нужна.

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

                                                                                                                                          Другими словами, если человек привык ездить в Икарусе, и ему неудобно без поручней в Мазерати (не за что держаться стоя), то это не недостаток Мазерати, это недостаток человека, что он так долго адаптируется к новым для себя реалиям.
                                                                                                                                            +3
                                                                                                                                            «War is peace, generics are slavery, interface{} is bliss.»
                                                                                                                                              0
                                                                                                                                              Ну Оруэлла все читали, давайте что-то по сути.
                                                                                                                                                +3
                                                                                                                                                Давайте по сути.
                                                                                                                                                а я о шаблонах и паттернах которые человек не хочет или не может пересмотреть по мере того, как он пытается освоить новый язык

                                                                                                                                                Какие паттерны предлагает Go взамен тех, которые «не хотят пересмотреть»?

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

                                                                                                                                                Какой майндсет предлагает Go в таком случае?
                                                                                                                                                  +5
                                                                                                                                                  Давайте.
                                                                                                                                                  Я вот на хаскеле пишу. Он ни разу не класс-ориентированный ОО-язык, и набор паттернов в нём тоже совершенно иной. Но параметрический полиморфизм (читайте «генерики») там используется в хвост и гриву, как мощное средство повышения выразительности, производительности и надёжности. Сценарии его использования далеко не ограничиваются контейнерами, полиморфный код можно найти практически в любой библиотеке. И тут вдруг приходят гоферы и говорят, что если достичь просветления, сразу понимаешь, что генерики нинужны; но наглядных примеров, как без них резко всё делается проще, почему-то не показывают. При этом порой забывают, что язык несколько захардкоженных полиморфных типов всё-таки предоставляет (массивы, каналы, что ещё?), только другим их делать не даёт.
                                                                                                                                                    –3
                                                                                                                                                    Ну так давайте тогда называть вещи своими именами — вы пишете на языке Х, где жить нельзя без дженериков. Где-то вы читаете, что в другом языке дженериков (в привычном для вас понимании) нет, но при этом Google, Dropbox, CloudFlare и куча других компаний пишут высоконагруженный производительный софт.
                                                                                                                                                    Вместо того, чтобы задаться вопросом «Ага, видимо в других языках что-то немного иначе, чем в моем любимом Хаскеле, видимо нужно изучить вопрос повнимательнее» вы решаете просто «Язык — отстой, потому что там нет того и в том виде, к чему я привык в Хаскеле».
                                                                                                                                                    Ну окей, что тут скажешь.
                                                                                                                                                      +3
                                                                                                                                                      И что? Высоконагруженный производительный софт и на С пишут – и уж явно поболее, чем на го. Только вот сишники не говорят «всё городите свои классы и интерфейсы, вместо того чтобы пересмотреть свой подход и изучить вопрос повнимательнее», кроме совсем старозакалочных. Кстати, многие там без генериков тоже страдают, и костылят что-то на макросах и void*.
                                                                                                                                                      Ну и не надо мне каких-то левых мнений про отстой приписывать. Насчёт «в других языках что-то немного иначе» – параметрический полиморфизм в том или ином виде есть в подавляющем большинстве современных статических языков. Хаскель я привёл лишь в качестве примера, отличного от ООП-мейнстрима. Так что в данном вопросе это не он, это го такой особенный.
                                                                                                                                                        –3
                                                                                                                                                        Высоконагруженный производительный софт и на С пишут

                                                                                                                                                        Да на всем пишут. Вопрос — какой ценой.

                                                                                                                                                        параметрический полиморфизм в том или ином виде есть в подавляющем большинстве современных статических языков

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

                                                                                                                                                        Все эти «споры ни о чем» не отменяют одного — статья не имеет ни одного выдерживающего критики аргумента. Можно честно признаваться в том, что ты привык к чему-то, или больше душа лежит — но нести откровенную чушь, выставляя это «минусами языка» уж явно не стоит. Ради своей же репутации.
                                                                                                                                                          0
                                                                                                                                                          Класс, что ж народ так страдает тогда на этом «подавляющем большинстве современных статических языков», раз у вас там идиллия?

                                                                                                                                                          А кто на хаскеле страдает? Лично я там если и страдаю, то только потому, что батарейки не для всего завезли.
                                                                                                                                                            0
                                                                                                                                                            Можно честно признаваться в том, что ты привык к чему-то, или больше душа лежит — но нести откровенную чушь, выставляя это «минусами языка» уж явно не стоит.

                                                                                                                                                            А в статье, надо отметить, и написано совершенно честно: «поговорим о том, почему я не считаю Go полезным инструментом».

                                                                                                                                                            Еще в оригинале есть хорошая фраза, которую переводчик по каким-то причинам выпустил:

                                                                                                                                                            If you’re not interested in my opinion, or are ending up here via some Go news aggregator or something and want to show me the error of my ways, you probably needn’t bother.


                                                                                                                                                            Человек предлагает свое мнение, и предлагает он его по внешней просьбе.
                                                                                                                                                              +3
                                                                                                                                                              В русском переводе это звучало бы как пассивная агрессия. Разница в менталитете, вот это все. Нейтральный тон ftw!
                                                                                                                                                                +2
                                                                                                                                                                Угу, нейтральный тон, а что получилось — видно. Впрочем, было предсказуемо.
                                                                                                                                                              0
                                                                                                                                                              Не знаю, в каком порядке вы читали мой комментарий, но страдания были в абзаце про сишку, в которую полиморфизьма тоже не завезли, а не про подавляющее большинство.
                                                                                                                                                              Да на всем пишут. Вопрос — какой ценой.

                                                                                                                                                              Ну а я о чём. И без генериков пишут, и на го пишут. Только какой ценой? ;)
                                                                                                                                                                –1
                                                                                                                                                                Ну а я о чём. И без генериков пишут, и на го пишут. Только какой ценой? ;)

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

                                                                                                                                                    Мне интересно как живётся без дженериков. Самое простое применение дженериков — параметризированные контейнеры. Интересно как с этим в Go.

                                                                                                                                                    А вы в ответ — храните interface{}. Я так понимаю это как в Java хранить Object. То есть ответ такой, что сделать параметризированный контейнер невозможно.

                                                                                                                                                    С другой стороны вы утверждаете, что если человек кастит к interface{}, то его надо гнать. Создаётся впечатление, что приведение к interface{} неприемлемо везде, кроме случая с контейнерами.

                                                                                                                                                    Я правильно понял?
                                                                                                                                                      –1
                                                                                                                                                      Если мы так сильно требуем жесткую параметризацию, при этом у нас нет общего интерфейса(в случае го это означает, что у хранимых структур нету ни одного одинакового метода) для хранимых типов — то почему не использовать go generate на готовом шаблоне?
                                                                                                                                                        +1
                                                                                                                                                        А какие преимущества приносит отказ от дженериков? Чем их отсутствие улучшает жизнь настолько, что вы готовы пойти на использование генераторов кода?
                                                                                                                                                          0
                                                                                                                                                          Создатели языка говорят, что дженерики заметно усложняют язык и они пока не придумали достойную реализацию.
                                                                                                                                                            +4
                                                                                                                                                            Усложняют язык, или усложняют разработку компилятора?
                                                                                                                                                        –1
                                                                                                                                                        Я правильно понял?

                                                                                                                                                        Со скрипом, да.

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

                                                                                                                                                        Наоборот — я говорю, что злоупотребление пустым интерфейсом в Go есть признак борьбы с языком, а вы все увели в контейнеры.

                                                                                                                                                        Мне интересно как живётся без дженериков.

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

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

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

                                                                                                                                                        docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4/edit#

                                                                                                                                                        И мой вопрос — как часто вы пишете свои типизированные контейнеры? Можно в % от основного кода, или сколько раз в день, или сколько типизированных контейнеров вы написали в прошлом месяце?
                                                                                                                                                          +2
                                                                                                                                                          И мой вопрос — как часто вы пишете свои типизированные контейнеры? Можно в % от основного кода, или сколько раз в день, или сколько типизированных контейнеров вы написали в прошлом месяце?

                                                                                                                                                          Это неправильная постановка вопроса. Правильная — «как часто вы пользуетесь параметризованным контейнером». Ответ — часто. Я вот — практически ежедневно.