Почему дизайн Go плох для умных программистов

http://nomad.uk.net/articles/why-gos-design-is-a-disservice-to-intelligent-programmers.html
  • Перевод

На протяжении последних месяцев я использую Go для имплементаций Proof of Concept (прим.пер.: код для проверки работоспособности идеи) в свободное время, отчасти для изучения самого языка программирования. Программы сами по себе очень просты и не являются целью написания статьи, но сам опыт использования Go заслуживает того, чтобы сказать о нем пару слов. Go обещает быть (прим.пер.: статья написана в 2015) массовым языком для серьезного масштабируемого кода. Язык создан в Google, в котором активно им пользуются. Подведя черту, я искренне считаю, что дизайн языка Go плох для умных программистов.


Создан для слабых программистов?


Go очень просто научиться, настолько просто, что введение заняло у меня один вечер, после чего уже мог продуктивно писать код. Книга по которой я изучал Go называется An Introduction to Programming in Go (перевод), она доступна в сети. Книгу, как и сам исходный код на Go, легко читать, в ней есть хорошие примеры кода, она содержит порядка 150 страниц, которые можно прочесть за раз. Сначала эта простота действует освежающе, особенно в мире программирования, полного переусложненных технологий. Но в итоге рано или поздно возникает мысль: "Так ли это на самом деле?"


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


Так для чего же он был создан таким простым? Вот пара цитат Роба Пайка (прим.пер.: один из соавторов языка Go):


Ключевой момент здесь, что наши программисты (прим.пер.: гуглеры) не исследователи. Они, как правило, весьма молоды, идут к нам после учебы, возможно изучали Java, или C/C++, или Python. Они не в состоянии понять выдающийся язык, но в то же время мы хотим, чтобы они создавали хорошее ПО. Именно поэтому их язык должен прост им для понимания и изучения.
 
Он должен быть знакомым, грубо говоря похожим на Си. Программисты работающие в Google рано начинают свою карьеру и в большинстве своем знакомы с процедурными языками, в частности семейства Си. Требование в скорой продуктивности на новом языке программирования означает, что язык не должен быть слишком радикальным.

Что? Так Роб Пайк в сущности говорит, что разработчики в Google не столь хороши, потому они и создали язык для идиотов (прим.пер.: dumbed down), так чтобы они были в состоянии что-то сделать. Что за высокомерный взгляд на собственных коллег? Я всегда считал, что разработчики Google отобраны из самых ярких и лучших на Земле. Конечно они могут справиться с чем-то посложнее?


Артефакты чрезмерной простоты


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


Не очень выразительный


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


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


package main

import (
    "bufio"
    "flag"
    "fmt"
    "log"
    "os"
)

func main() {

    flag.Parse()
    flags := flag.Args()

    var text string
    var scanner *bufio.Scanner
    var err error

    if len(flags) > 0 {

        file, err := os.Open(flags[0])

        if err != nil {
            log.Fatal(err)
        }

        scanner = bufio.NewScanner(file)

    } else {
        scanner = bufio.NewScanner(os.Stdin)
    }

    for scanner.Scan() {
        text += scanner.Text()
    }

    err = scanner.Err()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(text)
}

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


Вот, к примеру, решение той же задачи на D:


import std.stdio, std.array, std.conv;

void main(string[] args)
{
    try
    {
        auto source = args.length > 1 ? File(args[1], "r") : stdin;
        auto text   = source.byLine.join.to!(string);

        writeln(text);
    }
    catch (Exception ex)
    {
        writeln(ex.msg);
    }
}

И кто теперь более читабельный? Я отдам свой голос D. Его код куда более читаемый, так как он более явно описывает действия. В D используются концепции куда сложнее (прим.пер.: альтернативный вызов функций и шаблоны), чем в примере с Go, но на самом деле нет ничего сложного в том, чтобы разобраться в них.


Ад копирования


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


package main

import "fmt"

func int64Sum(list []int64) (uint64) {
    var result int64 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

func int32Sum(list []int32) (uint64) {
    var result int32 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

func int16Sum(list []int16) (uint64) {
    var result int16 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

func int8Sum(list []int8) (uint64) {
    var result int8 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

func main() {

    list8  := []int8 {1, 2, 3, 4, 5}
    list16 := []int16{1, 2, 3, 4, 5}
    list32 := []int32{1, 2, 3, 4, 5}
    list64 := []int64{1, 2, 3, 4, 5}

    fmt.Println(int8Sum(list8))
    fmt.Println(int16Sum(list16))
    fmt.Println(int32Sum(list32))
    fmt.Println(int64Sum(list64))
}

И этот пример даже не работает для знаковых типов. Такой подход полностью нарушает принцип не повторять себя (DRY), один из наиболее известных и очевидных принципов, игнорирование которого является источником многих ошибок. Зачем Go это делает? Это ужасный аспект языка.


Тот же пример на D:


import std.stdio;
import std.algorithm;

void main(string[] args)
{
    [1, 2, 3, 4, 5].reduce!((a, b) => a + b).writeln;
}

Простое, элегантное и прямо в точку. Здесь используется функция reduce для шаблонного типа и предиката. Да, это опять же сложнее варианта с Go, но не столь уж сложно для понимания умными программистами. Который из примеров проще поддерживать и легче читать?


Простой обход системы типов


Я полагаю, читая это, программисты Go будут с пеной во рту кричать: "Ты делаешь это не так!". Что же, есть еще один способ сделать обобщенную функцию и типы, но это полностью разрушает систему типов!


Взгляните на этот пример глупого исправления языка для обхода проблемы:


package main

import "fmt"
import "reflect"

func Reduce(in interface{}, memo interface{}, fn func(interface{}, interface{}) interface{}) interface{} {
    val := reflect.ValueOf(in)

    for i := 0; i < val.Len(); i++ {
        memo = fn(val.Index(i).Interface(), memo)
    }

    return memo
}

func main() {

    list := []int{1, 2, 3, 4, 5}

    result := Reduce(list, 0, func(val interface{}, memo interface{}) interface{} {
        return memo.(int) + val.(int)
    })

    fmt.Println(result)
}

Эта имплементация Reduce была позаимствована из статьи Idiomatic generics in Go (прим.пер.: перевод не нашел, буду рад, если поможете с этим). Что же, если это идиоматично, я бы не хотел увидеть не идиоматичный пример. Использование interface{} — фарс, и в языке он нужен лишь для обхода типизации. Это пустой интерфейс и все типы его реализуют, позволяя полную свободу для всех. Этот стиль программирования до ужаса безобразен, и это еще не все. Для подобных акробатических трюков требуется использовать рефлексию времени выполнения. Даже Робу Пайку не нравятся индивиды, злоупотребляющие этим, о чем он упоминал в одном из своих докладов.


Это мощный инструмент, который должен быть использован с осторожностью. Его следует избегать пока в нем нет строгой необходимости.

Я бы взял шаблоны D вместо этой чепухи. Как кто-то может сказать, что interface{} более читаем или даже типобезопасен?


Горе управления зависимостями


У Go есть встроенная система зависимостей, построенная поверх популярных хостингов VCS. Поставляемые с Go инструменты знают об этим сервисах и могут скачивать, собирать и устанавливать из них код одним махом. Хотя это и здорово, есть крупная оплошность с версионированием! Да действительно, можно получить исходный код из сервисов вроде github или bitbucket с помощью инструментов Go, но нельзя указать версию. И снова простота в ущерб полезности. Я не в состоянии понять логику подобного решения.


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


Культурный багаж из Си


По-моему мнению, Go был разработан людьми, которые использовали Си всю свою жизнь и теми, кто не хотел попытаться использовать что-то новое. Язык можно описать как Си с дополнительными колесиками(ориг.: training wheels). В нем нет новых идей, кроме поддержки параллелизма (который, кстати, прекрасен) и это обидно. У вас есть отличная параллельность в едва ли годном к употреблению, хромающем языке.


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


Простота для собственной выгоды


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


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


Спасибо mersinvald за правки

Поделиться публикацией
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 364
    +9

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

      +3
      Не такая она и ужасная. Местами очень даже полезная, взять тоже Thrift. Всему есть место, кроме копипасты. Копипасте тоже есть место, но очень редко и в исключительных случаях.
        0

        Он же вроде для междуязыковой компиляции. А зачем такое в рамках одного языка?

          0
          У нас в проектах java immutables (которая практически кодогенерация) крайне помогает. Кроме того практически весь современный front-end js построен фактически на кодогенерации (babel, es6 support, react jsx)
            +1
            Что ни разу не облегчает отладку)
              0
              Про java immutables — попробуйте, там всё более чем прозрачно и отладка становится даже легче (!) за счёт легко предсказуемого поведения — речь об иммутабельных структурах всё-таки.

              Про babel/es6/jsx — есть же source maps, один раз на проект настроил и отлаживай себе.
              +5

              А еще есть lombok. И мне почему-то, кажется, что оба эти проекта подходят под пункт: "Мы боремся с косяками языка".


              А с js ситуация еще хуже, потому что там у людей еще и выбора нет.

                0
                Да, согласен! Но во всех этих случаях использование ванильных языков для чего-то большого приводит к на порядок-два большим затратам усилий и времени.
                +1
                Современный «front-end js» это настоящий ад, между делом.
                  +2
                  Да нормально, можно ехать.
                  image
                  0
                  И потом этот «кодосгенерированный» front-end js адски тормозит на клиентских устройствах.
                    +1
                    Интересно посмотреть ссылки на исследования, которые бы подтверждали Ваше утверждение. «кодосгенерированны» front-end js — из какого языка (js, ts, coffeescript, purescript, что-то ещё)? Каким генератором (babel? с какими плагинами? с какими настройками? tsc? jsx использовался? ...) Речь про телефоны? Планшеты? Ещё про какие клиентские устройства? «Адски тормозит» — это на порядок медленнее?

                    Без ответа на эти вопросы исходное утверждение выглядит как «кит сильнее слона».
                  0
                  Клиент и сервер могут быть написаны на одном языке, но быть независимыми проектами и разрабатываться разными командами. И тогда Thrift будет их стыковать. Т.е. и клиент, и сервер будут зависеть от некоторого третьего продукта, который будет представлять собой набор файлов Thrift.
                    +1
                    Что мешает в таком случае, если использование других языков не планируется, использовать не Thrift, а возможности языка и написать на нем ядро для обоих частей?
                      0
                      Ничего не мешает, это просто два разных подхода к решению одной проблемы. В каком-то одном случае будет удобен один вариант, в другом — другой.
                      Если ядро призвано только синхронизировать интерфейсы взаимодействия, то, возможно, проще будет поддерживать консистентность используя кодогенерацию, так как она обеспечивает меньшую свзяность проектов между собой. А если должна быть еще какая-то общая бизнес-логика, то лучше писать ядро.
                        0

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

                    0
                    И я не являюсь сторонником кодогенерации в Go, просто Вы одним махом записали всю кодогенерацию, как нечто ужасное.
                    А если вернуться к Go, то она еще и реализована довольно не удобно — ее нужно запускать каждый раз в ручную (по крайней мере из того, что я слышал).
                    Если уж кодогенерацию использовать, то модификация исходников для кодогенерации должна автоматически приводить к перегенерации кода в момент компиляции, а этого в Go нет.
                  +4
                  Кодогенерация считалась всеми простой, понятной, и в общем-то часто используемой вещью до появления IDE… которые её приватизировали.

                  Разработчики Go — не были фанатами IDE и потому использовали «старый стиль», когда кодогенерация является одним из инструментов, а не «табу», с которым борются всеми возможными способами…
                    –2

                    Это где же в современных ide кодогенерация?


                    Ну и плоха она по ровно одной причине: результат часто плохо читаемый и нужно ещё дополнительно учить инструмент кодогенерации и дрессировать его. А все для того, что бы обойти косяки языка (например, разницу между примитивными типами и объектами в Java).

                      +1
                      Могу вспомнить как минимум resource файл в VisualStudio. Можно статично через диалоговое коно указать путь к файлу. IDE ещё на прекомпиляции проверит что такой файл существует и сгенерирует статичный класс. Очень удобно например вынести все sql файлы в такой ресурс, а потом в месте использования заявки написать что то вроде:
                      var result = await db.Query(SQLResources.GetProducts);
                        +2

                        e.g: IDEA

                          +11
                          Это где же в современных ide кодогенерация?
                          Везде. Начиная от автоматического создания кучи бойлерплейта Wizard'ами, до вполне себе «классической» кодогенерации вещей типа R.java.

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

                          Ну и плоха она по ровно одной причине: результат часто плохо читаемый и нужно ещё дополнительно учить инструмент кодогенерации и дрессировать его.
                          Ну насчёт читабельности — это уж что вы сделаете, то и будет… А что инструмент нужно учить — ну так библиотеки, которыми вы пользуетесь тоже, как бы, правильно использовать без обучения не получится.
                            +1
                            Просто считается, что когда IDE геренирует тонны бойлерплейта, которые потом вставляются в ваш проект и засоряют его тоннами строк кода, который вы не писали, то это — хорошо.

                            Я так не считаю. Разве что в случае с ресурсными файлами, как мне указали правильно, и, например, настройкой GUI через стороннее приложение.


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

                              –4
                              Разве что в случае с ресурсными файлами, как мне указали правильно, и, например, настройкой GUI через стороннее приложение.
                              А чем ресурсные файлы уникальны? Чем ORM, RPC, FSM хуже? Тем, что ваша IDE их не знает? Ну так научите! Или успокойтесь уже и признайте, что «магическая лицензия» для кодогенерации не нужна.

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

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

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


                                Опять же, вы приписываете мне какую-то странную приверженность IDE и "магической лицензии", но я просто считаю кодогенерацию не очень удобной и стараюсь ее избегать как можно чаще. Особенно в рамках одного языка, где казалось бы фич языка должно хватить. Но вот господам с Go и Java приходится страдать.

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

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


                                  if err != nil {
                                      return nil, err;
                                  }
                                    0
                                    Кодогенерация вместо дженериков в языке — это, несомненно, костыль. Но неясно, насколько велика проблема. Мне, на практике, дженерики не были так уж сильно нужны и особых проблем я от необходимости поддерживать их руками никогда не испытывал. Возможно в тех, проектах, которые делаете вы — ситуация другая, было бы интересно посмотреть на проект, где дженерики занимают столь существуенную часть, что их отсутствие реально мешает.

                                    Берите любой крупных проект на go и попробуйте сделать grep "interface{}" -R . в его репозитории. Я не эксперт, но мой взгляд, почти каждый interface{} будет из-за проблемы с отсутствием дженериков. Я вот только что грепнул alertmanager и prometheus. И даже в alertmanager нашлось место этому чуду:


                                    ./template/template.go:func (t *Template) ExecuteTextString(text string, data interface{}) (string, error) {
                                    ./template/template.go:func (t *Template) ExecuteHTMLString(html string, data interface{}) (string, error) {
                                    ./template/template.go:type FuncMap map[string]interface{}
                                    ./template/internal/deftmpl/bindata.go:func (fi bindataFileInfo) Sys() interface{} {
                                      0
                                      Go подход к ошибкам просто не работает, если не ошибусь, товарищи авторы языка об этом в курсе и задача переосмыслить и предложить новый подход к работе с ошибками значится в задачах go 2.0
                                    +2

                                    Я всегда считал, что наоборот: код, сгенерированный визардами и т.п. — это плохо. Во первых, если внести в него изменения — при повторной генерации они пропадут. Во вторых, сгенерённый код не должен попадать в version control. В третьих, это вообще что-то вроде obj-файла, в нормальных условиях мне не надо его видеть.
                                    Короче: кодогенерация на этапе сборки — нормально, кодогенерация при написании кода — фу-фу-фу.


                                    Ну а "считается" — вроде как считается, что стандартные инструменты кодогенерации лучше самописных, поэтому мы наворачиваем горы темплейтов в C++ там, где код мог сгенерить скрипт из пяти строк...

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

                              Когда хочется написать чтото действиетельно сложное, (пытаясь простыми средствами реализовать сложную конструкцию или недостающую) то обычно простой код может превратиться в очень труднопонимаемый.
                                +2
                                Попробуйте язык D, который приводится в качестве примера в статье. Нативный код с GC, нет зоопарка разных компиляторов. Я использую его для решения задач из HackerRank.com и мне D показался отличным языком для написания алгоритмов.
                                  +1

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


                                  Компилятор, как и stdlib всё еще имеют баги, которые препятствуют использованию D в продакшне. Увы, это язык скорее "для души" нежели для работы.

                                    0
                                    Года 2 назад так и было, сейчас довольно редко можно наткнуться на очень уж критические баги.
                                      +3

                                      Ну хз, у нас сейчас переписывают на Rust то, что было на D именно из-за нестабильности языка и багов.

                                        +1
                                        У меня есть крупный проект клиента MMORPG на OpenGL на D.
                                        В начале разработки(4-5 лет назад) постоянно натыкался на баги в компиляторе/стандартной библиотеке. За последний год если только несколько багов в новой функциональности нашёл.
                                        Единственная проблема крупная на данный момент — консервативный GC, который в моём клиенте умудряется течь, чем несказанно портит жизнь.
                                        Главная проблема комьюнити — они любят трепаться о всяких новых технологиях, но никто не хочет тот же самый GC сделать precise.
                                          0

                                          У Вас клиент наверное под x86 без 64?

                                            0
                                            Под x86_64.
                                              0

                                              Странно что он течет под x86-64, т.к. по идее проблема "фальшивых" указателей на этой платформе стоит не так остро как на 32 разрядных системах.
                                              Жаль это слышать, надеюсь они наконец-то дотестят и сольют пулл реквест precise gc с мастером.


                                              А сколько примерно объектов в памяти у Вас в среднем? Просто для статистики, хочу лучше понять масштаб проблемы уктечек на стандартном GC

                                                +2
                                                issues.dlang.org/show_bug.cgi?id=18005
                                                Как можно видеть, даже создание 1 массива без указателей заставляет приложение течь на Windows особенно.
                                                Точное число я не измерял, но из-за этого приложение быстро зажирает под несколько гигабайт, даже если активных данных — 90 МБ.
                                    0
                                    А как оно будет через 10 лет? Сможете скомпилировать и запустить код, написанный сегодня?

                                    Это один из важгейших вопросов — но я не понимаю что разработчики D вообще про него думают…
                                    0

                                    Можете попробовать Nim, там тоже нативный код с опциональным GC, к тому же ведётся работа над деструкторами, кросс-компиляция как в Си (Nim компилируется в Си), никаких виртуальных машин и максимальная производительность (на уровне близком к чистому Си при правильном использовании языка)

                                      0

                                      Я все пытаюсь перейти на Nim как на основной язык для работы. Мешает только отсутствие развитого комьюнити и отсутствие зоопарка готовых либ, как в питоне, на котором я сейчас пишу.

                                    +8
                                    Автор не понимает целей и задач Гугла при разработке этого языка, поэтому сетует на то, что Go — это такой «С для дураков», а надо было вместо него внедрять что другое, с нативным ООП, с шаблонами, с выводом типов. D, например, или Rust, или вообще ЯФП какой-нибудь.
                                    Так вот, примерно 90% задач гугла вполне решается на этом самом «С для дураков» без использования кодогенерации, рефлексии, шаблонов, ООП и чего либо еще, и самое главное, что в итоге написанный разработчиками любого уровня код на Go смогут понять любые другие разработчики, даже если они в компании работают сутки и пришли сразу после ВУЗа.
                                    Более того, при уходе всех оригинальных разработчиков из команды проект не придется выбрасывать весь, потому что в нем никто не может разобраться, а получится передать другой команде обычных программистов, и они смогут подхватить его в относительно короткие сроки.
                                    Простота поддержки, простота отладки и поиска ошибок, доступность даже для новичков, и минимальные шансы выстрелить себе в ногу — вот что нужно компаниям уровня Гугла для большей части их кода. А оставшуюся меньшую часть можно писать на чем угодно, хоть на ассемблере, если есть такая необходимость.
                                      +9
                                      примерно 90% задач гугла вполне решается на этом самом «С для дураков»

                                      Откуда такая цифра «90%»? Всякие intelligent personal assistant'ы, беспилотные автомобили и другие AI-проекты, которыми так годится Гугл, входят в эти 90% задач? А Google Chrome?
                                        +1
                                        Грубая оценка по опыту работы в другой большой компании похожего уровня.
                                        Из всего вышеперечисленного только Chrome уже написан, и браться его переписывать на Go с нуля нет никакого смысла, все остальное — почему нет? Для хардкорной математики все равно будут использованы готовые библиотеки на С или Фортране (FFI у языка есть, сопряжение хоть и не без проблем, но работает), а для основной grunt work язык Go вполне подходит. Они на нем теперь даже initramfs пишут, так что я не удивлюсь, если напишут и что-нибудь из ML (AI все же слишком сильный термин, на мой взгляд).
                                          0
                                          Из всего вышеперечисленного только Chrome уже написан, и браться его переписывать на Go с нуля нет никакого смысла
                                          Помимо смысла: писать хороший GUI без богатого ООП очень трудно, хотя и возможно.
                                          AI все же слишком сильный термин, на мой взгляд
                                          Если assistant по замыслу не просто «болталка», вроде Элизы, то AI там нужен мощнее, чем сегодня доступен. Т.о. существующих библиотек явно недостаточно. Нужны собственные научные разработки. Аналогично про беспилотный автомобиль. (Или есть способ прятать внутри живого пилота :)
                                            0
                                            Помимо смысла: писать хороший GUI без богатого ООП очень трудно, хотя и возможно.
                                            Вот как раз тот ООП, который есть в Go для написания GUI подходит куда больше, чем «классический».

                                            Но GUI в Chrome в основном на JavaScript всё равно, так что тут скорее проблема в специфике продукта, а не в том, что GUI на Go сложно писать…
                                              +8
                                              в Go для написания GUI подходит куда больше

                                              Когда в руках молоток, все вокруг — гвозди
                                                –3
                                                Причём тут молоток? При создании GUI вам регулярно нужно связывать между собой разнородные обьекты.

                                                Что в модели ООП пропогандируемой С++/C#/Java сделать не так-то просто: недаром все C++ библиотеки так или иначе завязаны на кодогенерацию. Явную (как в MFC или Qt) или неявную (как в WTL — через шаблоны). В CLOS этой проблемы нет и, собственно, своременный GUI разрабатывался на этой обьектной модели ещё до того, как его увидел Jobs.
                                                  0
                                                  Не совсем понимаю что такое «связывать между собой разнородные объекты». Не могли бы вы пояснить какие именно связи имеются в виду?
                                                    0
                                                    Вот те самые, которые в Qt делаются через кодогенерацию, а в MFC и других подобных тулкитах — через ещё более сташные извращения.

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

                                                    Впрочем, как я уже сказал, полноценных библиотек виджетов, сравнимых с Qt для Go пока нет, так что сказать на 100%, что всё пройдёт гладко и удастся обойтись без костылей типа кодогенерации (а макросы это тоже кодогенерация, пусть и примитивная) — пока нельзя.
                                                      +1
                                                      В таком случае я не понимаю претензий к C#, где то же самое является частью языка (аналог сингала — это событие, слотом может выступать любой метод подходящей сигнатуры) безо всякой кодогенерации.
                                                        +1
                                                        Замечание принято. Да, пожалуй в C# этой проблемы нет. Там среди прочего всякого добра напихано и решение этой проблемы тоже.
                                        +3
                                        Так вот, примерно 90% задач гугла вполне решается на этом самом «С для дураков» без использования кодогенерации, рефлексии, шаблонов, ООП и чего либо еще, и самое главное, что в итоге написанный разработчиками любого уровня код на Go смогут понять любые другие разработчики, даже если они в компании работают сутки и пришли сразу после ВУЗа.

                                        Интересное умозаключение. А на самом деле большинству приходится делать всякие сервисы, высокопроизводительные серверы, машинное обучение итд. В итоге Go стал по большей мере более производительной альтернативой Python для написания несложных демок/скриптообразного кода.
                                          +4
                                          Простота поддержки
                                          Спагетти-кода, который го провоцирует?

                                          простота отладки
                                          В копипасте?

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

                                            Ну да, как же… Gotchas and common mistakes in Go
                                            По количеству WAT Go может влёгкую побороться за второе место после JavaScript.

                                              +2
                                              По количеству WAT Go может влёгкую побороться за второе место после JavaScript.
                                              Только за третье и то не факт. Первое-второе места забиты намертво за JavaScript'ом и PHP, которые всё никак не выяснят какой из них кривее.
                                                +3
                                                Хотите сказать кто вообще способен хотя бы догнать С++ и PL/1? Что-то во времена студенческие я не видел ни одного учебника по С++ (в особенности от авторов языка) в котором хотя бы 4/5 примеров компилировались, а с тех пор в язык только добавляют и добавляют новые способы стрельнуть себе в ногу.
                                                  –2
                                                  Что-то во времена студенческие я не видел ни одного учебника по С++ (в особенности от авторов языка) в котором хотя бы 4/5 примеров компилировались
                                                  Если что-то не скомпилировалось — так это ж хорошо: вы увидите проблему и её исправите. Это вообще не проблема.

                                                  А вот если оно скомпилировалось и делает не то, что ожидалось… это бяда. В этом отношении JavaScript и PHP не переплюнуть… хотя C++ и старается, да.
                                                    +3
                                                    Пример-то я исправлю, но я не могу исправить учебник. А кто-то по нему учится…
                                                      0
                                                      Если что-то не скомпилировалось — так это ж хорошо: вы увидите проблему и её исправите. Это вообще не проблема.

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

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

                                                          Если в книге 3/4 примеров не компилируются или крашатся не из-за ошибок автора-издателя, а из-за того, что раз в год в языке происходят сильные изменения, ломающие обртаную совместимость, то к качеству языка это имеет прямое отношение.

                                                            +1
                                                            Несомненно. Но с учётом того, что у меня есть знакомый, который отличненько осваивал курс, написанный под Turbo C 2.0 с использованием последней версии GCC и Clion… я думаю что проблема-таки в издателях… Ну или в горе-программистах, которые в учебных примерах используют всякие <conio.h>, которые большинством компиляторов никогда не поддерживались.
                                                        0
                                                        В этом отношении JavaScript и PHP не переплюнуть… хотя C++ и старается, да.

                                                        Не знаю за плюсы, но указатели в чистом С- это такой реактивный многозарядный гранатомёт со сверхчувствительным спусковым механизмом, по сравнению с которым сравнение строк в этих скриптовых языках- полнейшая фигня.
                                                          +1
                                                          Теоретически — да. А практически — в типичном web-магазинчике будут десятки миллионов строк кода на C/C++ (не только ядро операционной системы, но и всякие SQL-базы данных, акселераторы и прочее — это ведь всё на C/C++ написано), а сверху — тысяч сто строк на PHP или Ruby. При этом на каждую дыру в ядре будет пара SQL-уязвимостей в движке.

                                                          Так что да — указатели они, конечно, ужасны и опасны, но до уровня JavaScript/PHP — не дотягивают…
                                                            0
                                                            Вы серьёзно сравниваете вылизанный код ОС, интерпретатора и БД, используемый на миллионах инсталяций, с уникальным наколеночным кодом студента на подработке (утрирую)?
                                                          0
                                                          Это был толстый намёк, что даже авторы стандарта не знают его от и до и (sic!) раз даже простой пример набрать без ошибок не могут. А без полноценного понимания языка говорить о совместимости его функций (= отсутствии косяков в дизайне) как-то смешно.
                                                          В этом смысле php намного лучше — пространства для косяков меньше, дефекты дизайна постепенно исправляются, глупости перестают интерпретироваться (в отличие от С++).
                                                  –6
                                                  И кто теперь более читабельный? Я отдам свой голос D. Его код куда более читаемый, так как он более явно описывает действия.

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

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

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

                                                  Из всей статьи только дженерики адекватная критика. Их недостает и interface{} нужно всеми силами как-то выпиливать из стандартной библиотеки. «культурный багаж Си» так вообще ересь. Инкапсуляция и абстракция достигается через интерфейсы. Еще большая ересь это критика процедурного стиля. Какая разница как он ощущается, если этот стиль программирования понятен и прост для чтения?

                                                  Такое ощущение, что автор статьи студент, которому лишь бы поиграться с языком, в котором побольше фич. Человек будто совсем не понимает задач компаний вроде Гугл.
                                                    +2
                                                    По поводу билдов немного странный аргумент. Почему нельзя было сделать нормальную систему пакетов, как смог тот же Nim или Crystal? Версии по коммитам это просто ад.
                                                      –1
                                                      Потому что нормальная система пакетов обычно зависит от стороннего сервиса, на который надеяться себе же дороже. Не так давно уже была забавная история с node.js что ли, когда удалили безобидный пакет. Банально интернет может не работать и что, вся компания будет сидеть и ждать его возвращения? В конечном итоге приходит понимание, что наверное стоит поднять тот же самый сервер локально, чтобы он хотя бы кэшировал зависимости. Либо окончательное прозрение, что стоит все зависимости тащить с собой в репозиторий в отдельной папочке «vendor». Судя по всему, компании уровня Гугл и даже куда меньше именно к последнему и приходят. Конечно, не идеал и не удобно бывает, но вариантов других особо нет.
                                                        +5

                                                        А как эти две вещи связаны? Храните где хотите, но отвяжите пакеты от VCS и заставте людей делать нормальные пакеты с версиями. Вам же его скачать то все равно с внешнего сервиса нужно.

                                                          –3

                                                          Видимо, гугл считает, что им удобнее вот так. У них, к примеру, весь C++ код хранится в едином репозитории и собирается целиком. Казалось бы, милое дело — выделить модули, каждый модуль разрабатывать независимо в своем репозитории (и секюрность, и размер репо и билда уменьшить, и команды друг другу мержи и билды ломать не будут), стабильные оттестированные релизы пакетировать и выкладывать на тот же внутренний сервер — красота, все по святцам! Но нет, гуглу оказалось объективно лучше держать все в одной куче и жить на "острие".
                                                          Есть такая поговорка "ты не гугл". То, что может казаться (и быть) хорошим и приятным для нас с вами, для компании такого размера может был плохим и вредным. В частности, таким вредным они считают версионирование пакетов. Что логично — нетрудно обеспечить совместимость версии, если у тебя собирается пакет, зависящий от еще пары. Когда у тебя собираются тысячи и десятки тысяч пакетов, зависящих друг от друга, то менеджмент совместимых версий превращается в ад.

                                                            0

                                                            Когда у вас так много пакетов, у вас все равно ад.


                                                            Лично мне кажется, это потому, что google в целом может положить большой болт и тестировать новый функционал на 10% клиентов. Далеко не все компании так могут, так как не монополисты все-таки :)

                                                              0
                                                              размер билда? В плюсах же по идее ты не платишь за то что не используешь.
                                                                0

                                                                Я о суммарном размере билда. Если кто-то изменяет библиотеку в модульной архитектуре, то им надо только проверить, что она собирается; сборка, проверка вышестоящих библиотек — это задача тех, кто будет обновлять зависимости. Если кто-то изменяет библиотеку в гугле, то им надо собрать всё, что ее использует, и поправить всё сломавшееся. Гугл, НЯЗ, использует виртуальную ФЗ (как ClearCase MVFS, чтобы не убивать место на HDD и время программистов миллионами файлов из репо), распределенные билды и хитрые билд-системы, чтобы скорость билдов была адекватной, но билды все равно должны быть сделаны и артефакты все равно должны куда-то упасть.

                                                                  –1
                                                                  Если кто-то изменяет библиотеку в модульной архитектуре, то им надо только проверить, что она собирается
                                                                  А работоспособность кто проверять будет? Пушкин?

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

                                                                  Когда у вас между проектами — административная граница, то у вас, в общем-то, нет выбора. Но если её нет — общий репозиторий лучше. Собственно все большие проекты так всегда и собирались — и UNIX, и OS/360 и многие их последователи.

                                                                  Только GNU/Linux, по политическим причинам, устроен не так. Ну так то — вынужденная мера, а не то, к чему стоит стремиться.

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

                                                                    Но если её нет — общий репозиторий лучше.
                                                                    Я с этим спорю, что ли? Я говорю, что для "нас с вами" (use-case типичный опен-сорс проектик) удобнее релизы и версионируемость. Для гугла — удобнее монорепозиторий и жизнь на "голове". Go — язык гугла для гугла; логично, что они использовали для зависимостей в Go ту же философию. Поэтому и статья в целом ("мне Go не нравится, а я знаю D умный программист => Go не для умных программистов"), и тот комментарий, на который я отвечал ("для меня пакеты удобнее => Go нужны зависимости в пакетах, а не голова репозитория"), мне кажутся наивными. Я попытался намекнуть, что у гугла может быть точка зрения, отличная от ТЗ типичного Васи Пупкина, но это не оценили.

                                                                    А в случае с несколькими проектами и несколькими репозиториями это не так?
                                                                    Не так, по той причине, что не надо проверять собираемость вышестоящих библиотек. Грубо говоря, в "модульном" варианте выпуск новой версии Abseil влечет за собой билд библиотеки Abseil и прогон ее автотестов. В монорепозитории — (инкрементальный, но) ребилд всего репозитория из тысяч проектов, и прогон всех автотестов всех этих библиотек.
                                                              0
                                                              С версиями вот такие рассуждения.

                                                              У нас есть некий код, допустим он типизирован и есть внешний интерфейс у импортируемого модуля.
                                                              Что в таком случае будет означать изменение версии?
                                                              Изменение API модуля? Совсем не обязательно (в semver это предполагает лишь в мажорных версиях). А что тогда? Непонятно, все равно придется проверять, что же изменилось вручную.
                                                              Получается, что система версий не типизируется, а значит не автоматизируется.
                                                              А значит, весь вопрос уже заключается в том, как вести для людей лог изменений модуля, и я вовсе не уверен что безликие 3 циферки что-то значат.
                                                              И логика без цифр такая.
                                                              Если это внутреннее изменение (ну, фикс безопасности, к примеру), то и не нужны никакие новые цифры. Если изменение API, то, опять же, компилятор должен ругнуться. Если изменения API нет, но поведение изменилось — нужно менять название пакета, а старый оставить в покое, обратная совместимость, все дела.
                                                              Привязка же к коммитам удобна при параллельной разработке, но внутри одной компании.

                                                              А эти все куча цифр в некоторых пакетных менеджерах — попытка костылем подпереть отсутствие статической типизации. Все равно не работает.

                                                                +8

                                                                Версионность выполняет ровно две функции:


                                                                • Человекочитаемость. Когда я вижу, что пакет версии 2.1.5, а я использую версию 0.5.1, то мне надо обновится (и вполне вероятно, поиметь проблем). А когда я вижу, что использую коммит 249f069bdf09be30258c604be27fdce51694706f вместо 249f069bdf09be30258c604be27fdce51694706f это мне ни о чем не говорит.
                                                                • Исправность. Есть такая штука, что далеко не у всех людей каждый коммит содержит код, который вообще собирается. А каждая версия программы должна собираться, без этого никак.

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


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

                                                                  +4
                                                                  Вы специально одинаковые хэши написали?
                                                                    0
                                                                    Хм… нет, криво скопировал.
                                                                    –1
                                                                    Есть такая штука, что далеко не у всех людей каждый коммит содержит код, который вообще собирается.
                                                                    И вот «с этой штукой» и нужно бороться. Trybots для этого и существуют.

                                                                    Более того, версионность позволяет не только жестко фиксировать версии, но так же и задавать диапазоны версионности, что бы у вас не возникало по три-пять разных версий пакетов в одном и тот же проекте.
                                                                    Откуда у вас возьмутся «три-пять» версий пакетов (и вообще пакеты, как таковые) при использовании одного репозитория? Или вы про master/release/release-stable и т.п. ветки? Ну так они «внутри себя» все согласованы…
                                                                      0
                                                                      Откуда у вас возьмутся «три-пять» версий пакетов (и вообще пакеты, как таковые) при использовании одного репозитория? Или вы про master/release/release-stable и т.п. ветки? Ну так они «внутри себя» все согласованы…

                                                                      Давайте начнем с простого. Если вы работаете в google/facebook/another company где все проекты лежат в одном репозитории (на самом деле в google и facebook это уже тоже не так, у них есть open source) и вообще никак не завязаны на open source либы — я за вас рад.


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

                                                                        –5
                                                                        на самом деле в google и facebook это уже тоже не так, у них есть open source
                                                                        Угу — и это позволяет посмотреть как всё устроено.

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

                                                                        Когда вы скачиваете себе два разных проекта к себе в репозиторий, то они обязаны работать с той версией пакетов, что у вас есть. Можете посмотреть в Chrome или Android: пакеты там не дублируются (за исключением резко патологических случаях типа AngularJS vs Angular, или Pel5 vs Perl6 где разные «версии» лучше рассматривать не как разные версии одного и того же, а два совершенно разных продукта).

                                                                        Вот чтобы такую проблему не решать Go по умолчанию и берёт всё из trunk'а. Если ваши пакеты, в результате, не заведутся и не заработают — ну да, можно попробовать накостылить что-нибудь. Но по умолчанию — все пакеты должны использовать одной версии. Самой последней.
                                                                          +6
                                                                          То есть если в транке популярной библиотеки кто-то выложит новую версию, которая ломает совместимость, то по цепочке упадут все проекты, которые используют этот пакет, пока все их них не будут пофикшены?
                                                                            –1
                                                                            Ну не путайте стадии. В production всегда должны фиксироваться именно те версии, на которых прошли все тесты. Любое обновление по любому поводу (даже patch) может происходить только на стадии разработки. Так что да, упадут все проекты, и встанет очевиден вопрос, с чего это используется библиотека, которая ломает обратную совместимость. Но нет, упадут не в боевой версии, а у разработчиков.
                                                                              +7
                                                                              Я разрабатываю какой-то продукт и использую множество библиотек. Делаю `go get` и скачиваю из транка новые версии библиотек. Оказывается, что в одной зависимости нескольких моих зависимостей сломалась совместимость. Теперь моя разработка стоит пока все эти библиотеки не пофиксят совместимость с той, что внесла изменения?

                                                                              Обращу внимание, что gitflow не отрицает изменений, ломающих совместимость. То есть в мастер вполне может прилететь такая версия.
                                                                                –6
                                                                                Я разрабатываю какой-то продукт и использую множество библиотек.
                                                                                И вот в этот момент — у вас уже проблемы: если вы не понимаете что вы используете и допускаете использование бог-знает-чего, то кто ж вам судья, что у вас что-то сломалось?

                                                                                Обращу внимание, что gitflow не отрицает изменений, ломающих совместимость. То есть в мастер вполне может прилететь такая версия.
                                                                                Ничего не знаю про gitflow. Знаю что в gerrit есть кнопочка rollback, которая откатывает изменения без вытаскивания их в клиент и прочего. Вот именно на случай, когда в trunk попало что-то, что сломает кучу клиентов.
                                                                                  +1
                                                                                  используете и допускаете использование бог-знает-чего, то кто ж вам судья, что у вас что-то сломалось?

                                                                                  То есть, по вашему, идеология Гоу отрицает использование множества библиотек?

                                                                                  Вот именно на случай, когда в trunk попало что-то, что сломает кучу клиентов

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

                                                                                    Но у меня ведь нету доступа к такой кнопочке независимой библиотеки.
                                                                                    Сделайте клон — появится.

                                                                                    Но вообще идеолигия такая, да: trunk'и всех проектов должны быть совместимы.

                                                                                    Если какой-то проект постоянно ломает API trunk'а и заставляет использовать устаревшие версии — то от него лучше отказаться.
                                                                                      +5
                                                                                      Ох уж этот стокгольмский синдром. Я понимаю, что язык молодой, библиотек на все случаи жизни еще не написано, сейчас принято велосипедить на каждом проекте, но ведь скоро это изменится.

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

                                                                                        Вообще говоря версии тут вам ничем не помогут. А поможет фиксация ревизий. Которая через git submodules реализуется куда лучше. Но это не про го вроде.

                                                                                          0
                                                                                          Да нет, библиотек уже довольно много.
                                                                                          А вот подобный радикализм действительно встречается. Мне правда не понятно до конца зачем… Может потому, что в го идут те, кто хочет забыть все сложности и «просто писать код».
                                                                                            –1
                                                                                            Нет никакого «нормального управления пакетами». Чужой код — всегда чужой код. Хоть обвешайтесь циферками, leftpad будет вас ждать.

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

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

                                                                                            Но не надо обвинять инструменты, просто нужно разделять экспериментальный код, прототипы VS рабочий код.
                                                                                            Вот в первом случае, go get вам в руки, semver с ^ самой новой версией.
                                                                                            Во втором, жесткая фиксация, папка vendor с необновляемым кодом зависимостей, ну а в случае semver жесткий номер версии, вплоть до номера патча.
                                                                                              0
                                                                                              Еще раз, единственная причина, по которой вам может понадобиться обновить библиотеку — неожиданный критический баг. Это не требует никаких версий и уж точно не может ломать совместимость.

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

                                                                                                +3
                                                                                                Если библиотека достойная, то ее код уже готов к использованию

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

                                                                                                Ах, мир розовых плюшевых единорожков. Миленько. Есть или достойные библиотеки с идеальным кодом, или недостойные с плохим. И есть хорошие стартапы, которые пользуются достойными библиотеками и плохие стартапы, которые пользуются недостойными. И благо, что плохие умерли из-за того, что в Гоу такой хороший подход к управлению зависимостей. Святой Гоу очищает. Ох уж эти религиозные фанатики.

                                                                                                Хочу напомнить, что слабость синтаксиса Гоу очень сильно усложняет развитие библиотек (извините, я понимаю, что у вас в репозитории только идеальные библиотеки, которые развития больше не требуют, ибо они сразу написаны в финальной версии, но, очевидно, я из плохих стартапов и мои библиотеки не такие розовые и плюшевые). Так вот — нету ни аргументов-по-умолчанию, ни переопределения методов. В итоге, если мне надо добавить в метод параметр (ну простите, я не идеальный архитектор, не умею писать сразу финальный код) — я не могу вменяемо просто добавить в этот метод параметр не сломав совместимость.
                                                                                                  –4
                                                                                                  В итоге, если мне надо добавить в метод параметр (ну простите, я не идеальный архитектор, не умею писать сразу финальный код) — я не могу вменяемо просто добавить в этот метод параметр не сломав совместимость.
                                                                                                  Плохому танцору… Почему это не мешает разработчикам Linux (я имею в виду ядро), MacOS (я имею в виду Classic), Unix, Windows и многих других систем?

                                                                                                  Может проблема не в слабости языка, а в банальном нежелании думать о стабильном API заранее? Ну так в этом случае никакой синтаксический сахар не поможет…
                                                                                                    +5
                                                                                                    Это вы об этом?
                                                                                                    HWND hWnd = CreateWindow(  
                                                                                                            szWindowClass,  
                                                                                                            szTitle,  
                                                                                                            WS_OVERLAPPEDWINDOW,  
                                                                                                            CW_USEDEFAULT, CW_USEDEFAULT,  
                                                                                                            500, 100,  
                                                                                                            NULL,  
                                                                                                            NULL,  
                                                                                                            hInstance,  
                                                                                                            NULL  
                                                                                                        );  


                                                                                                    Уверен, они не рады необходимости тащить ужасное легаси и поддерживать отвратительный синтаксис подобного вида.

                                                                                                    Конечно, я понимаю, что можно заранее добавить параметров на все случаи жизни. Можно нанять штатного телепата. Уверен, в вашем мире единорожков именно так и делают.
                                                                                                      –4
                                                                                                      Уверен, они не рады необходимости тащить ужасное легаси и поддерживать отвратительный синтаксис подобного вида.
                                                                                                      Разумеется нет. Программисты — они такие. Им всегда хочется что-нибудь переписать с нуля и всё сделать «правильно». Но когда им позволяют это сделать… технологический лидер — становится бывшим.

                                                                                                      Конечно, я понимаю, что можно заранее добавить параметров на все случаи жизни. Можно нанять штатного телепата. Уверен, в вашем мире единорожков именно так и делают.
                                                                                                      Причём тут «мир единорожков»? Про телепатов — не знаю, но «добавить параметров» — это путь Windows. Есть ещё путь Linux/Unix: если нам нужен параметр в dup2, то появляется dup3 (а dup2, разумеется, остаётся).

                                                                                                      Есть много подходов, позволяющих сохранить обратную совместимость. И да, бывают случаи, когда без этого не обойтись. Скажем у GlibC вышла версия 1.0 в 1992м году, а в 1997м — вышла версия 2.0, сломавшая совместимость к чёртовой матери. Просто потому что подход, использованный в GLibC 1.0 оказалось практически невозможно использовать с ELFом. Но вот уже GLibC 2.26, вышедшая несколько месяцев назад — вполне совместима с GLibC 2.0, вышедшей в 1997м.

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

                                                                                                      Внутренние API, в рамках одного репозитория — другое дело: тут вы не предполагаете, а знаете, причём точно знаете — что нужно вашим клиентам. В случае же с публичным API — вы можете только предполагать… и очень часто — неправильно.
                                                                                                        +3
                                                                                                        Им всегда хочется что-нибудь переписать с нуля

                                                                                                        Я не говорил про «переписать с нуля» вообще-то, это уже ваши домыслы. Поломка обратной совместимости и переписывание с нуля — это совершенно разные вещи. Ну вот как Юнити к примеру. Сколько раз там ломалась совместимость, а они до сих пор на коне?

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

                                                                                                        То есть вы мне кинули статью, где описывается, что от Микрософта люди ушли из-за отвратительного API на более приятные технологии и шаг с значительным опозданием уже не спас ситуацию и вы считаете, что это как-то подтверждает вашу теорию?

                                                                                                        Более того, это как раз подтверждает мои тезисы — Гоу отвратительный язык, потому что в нем значительно сложнее развивать API без поломки обратной совместимости. В C# я могу добавить метод с тем же названием, но другими параметрами. В C# я могу добавить в метод новый аргумент и добавить ему значение по-умолчанию и этим сохранить совместимость. В го такого нету, это плохой язык. Если мне необходимо добавить второй аргумент в метод — мне ПРИХОДИТСЯ ломать обратную совместимость или давать другое название метода, менее подходящее — типа dup2
                                                                                                          –6
                                                                                                          То есть вы мне кинули статью, где описывается, что от Микрософта люди ушли из-за отвратительного API на более приятные технологии и шаг с значительным опозданием уже не спас ситуацию и вы считаете, что это как-то подтверждает вашу теорию?
                                                                                                          Основной тезис статьи: каким бы ни был API — но отказ его поддержки, как правило, приводит к тому, что люди от вас уходят, да. Очень подробно и с примерами. Скажем на тот же Unix/Linux где API нельзя сказать, что уж прям верх совершенства — но он стабилен (если не касаться десктопа, увы).

                                                                                                          При этому уходят люди не на более приятный API (на что был рассчёт у создателей C# и всей .NET экосистемы), а на более доступный.

                                                                                                          В C# я могу добавить метод с тем же названием, но другими параметрами.
                                                                                                          А почему вы считаете, что это хорошо?

                                                                                                          В C++ это, в принципе, тоже возможно — однако Google рекомендует этого не делать.

                                                                                                          Если мне необходимо добавить второй аргумент в метод — мне ПРИХОДИТСЯ ломать обратную совместимость
                                                                                                          Да что это за танцор, блин, такой… Никому не приходится — а ему приходится…

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

                                                                                                          Ситуация с языком Go, в общем, довольно странная: сам язык — действительно достаточно молод, но вот его разработчики — не совсем. Соотвественно хайпа в нём мало… что не мешает ему иметь сообщество разработчиков, сравнимое по размеру с такими языками, как Swift или Ruby… что достаточно удивительно, если вы вспомните, что Google не продвигает его так агрессивно, как Apple продвигает Swift и шума, подобного тому, что поднят вокруг Ruby-on-Rails тоже нету.
                                                                                                            +5
                                                                                                            Соотвественно хайпа в нём мало… что не мешает ему иметь сообщество разработчиков, сравнимое по размеру с такими языками, как Swift или Ruby… что достаточно удивительно, если вы вспомните, что Google не продвигает его так агрессивно, как Apple продвигает Swift и шума, подобного тому, что поднят вокруг Ruby-on-Rails тоже нету.

                                                                                                            Не буду говорить за всех, но лично я узнал о существовании Ruby и Ruby-on-Rails когда игрался с бесплатными системами управления проектами и наткнулся на Redmine. Про Swift слышал чуть-чуть. Зато про Go из каждого "утюга".


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


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

                                                                                              +3
                                                                                              Сделайте клон — появится.

                                                                                              В нормальных системах (как хаскелевский stack, например) вместо клона можно обойтись commit hash'ем нужной ревизии.

                                                                                              Если какой-то проект постоянно ломает API trunk'а и заставляет использовать устаревшие версии — то от него лучше отказаться.

                                                                                              В проде я от него откажусь, вероятно, да. В процессе разработки — нет. В моём опыте несколько раз имело смысл взять на потестировать библиотеку, у которой не то что транк всё время ломается, а ни одного публичного релиза не было.
                                                                                          0
                                                                                          Для реальной разработки в go сейчас уходят от go get всех пакетов. Собираются включить dep в стандартный набор утили, когда это будет неизвестно, но его уже сейчас можно использовать. (ну либо аналоги). Все они используют как указатель версии пакета тэги в SemVer. В таком случае калечащие изменения должны выкатываться под новой major версией. А менеджер зависимостей не должен сам major обновления применять.
                                                                                            0
                                                                                            в go сейчас уходят от go get всех пакетов

                                                                                            То есть `go get` таки плохой? А почему тут жертвы его защищают?
                                                                                            0
                                                                                            Делаю go get и скачиваю из транка новые версии библиотек

                                                                                            А go get нельзя привязать к тегу?

                                                                                0

                                                                                SemVer.

                                                                                  –2

                                                                                  Как раз недавно рассказывал, почему мы отказались от версионирования на фронте.


                                                                                  unsafePtr у шарпа и явы дженерики — это не шаблоны, а полиморфные типы.


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

                                                                              –1

                                                                              Потому что создателям go "далеко за ..." и многое им видится "ненужным, излишним", после проходят годики и начинаются писаться статьи вроде Dave Chany и техническом долге go и том, что если язык назвался mainstream, то от него ждут определенных вещей: управление зависимостями, generics. Но создатели языка действуют в формате "если мы сомневаемся, то не делаем ничего и ждем".
                                                                              Язык golang великолепен в большом поле задач и за год вполне можно взгрустнуть об отсутствии обобщенных типов лишь раз или два(грусть чаще накатывает от фанатов golang). Но вот станет ли язык mainstream — вопрос открытый.
                                                                              По мне, несмотря на все громкие заявления о том, как будут вводиться изменения в язык (а таких заявлений была масса в 2017 году), развитие языка в 2017 провалилось: невнятный и непродуманный контекст, поломанные плагины (эпичная "бага" с тем, что они не работают нигде, кроме unix), алиасы, sync.map — это скорее недоразумения, чем развитие языка.
                                                                              Но время покажет.

                                                                                +5
                                                                                Потому что язык был сделан для Гугла, где весь код живет в одной репе и собирается с головы/какой-то версии коммита.
                                                                                +3
                                                                                На D написан типичный ворох специальных символов, который надо декодировать каждый раз, когда ты приходишь к куску кода, который первый раз видишь или позабыл

                                                                                А можно, пожалуйста, подробнее для тех кто не в курсе?

                                                                                  +6
                                                                                  На D написан типичный ворох специальных символов, который надо декодировать каждый раз, когда ты приходишь к куску кода, который первый раз видишь или позабыл.

                                                                                  Я не пишу на D, но пример там очень понятный, поскольку похож на любой современный язык, кроме Go

                                                                                  +4
                                                                                  Не понял: в статье ругают Go или рекламируют D? Объясните, я просто dumbed down (из Google).
                                                                                    –7
                                                                                    ругают Go или рекламируют D?

                                                                                    точно так. только по сниппетам кода понятно, что автор не дотягивает даже до туповатых, а умным себя считает только по факту того, что пишет на D (оказался умнее всех тех, кто не пишет на этом прекрасном языке)
                                                                                      –2
                                                                                      [offtop]
                                                                                      минусующие (как здесь, так и в карме) могли бы и высказать в чём я не прав, аргументами меня задавить, а не так — плюнул в спину и убежал
                                                                                      [/offtop]
                                                                                        +4

                                                                                        Вероятно за "автор не дотягивает даже до туповатых" и вообще переход на личности.

                                                                                          –4
                                                                                          [offtop]
                                                                                          Спасибо, мил человек, никогда бы и в голову не пришло, что на Хабре есть целый профсоюз «Защиты британских троллей от оскорблений за откровенно тупые набросы с интами». Буду знать.
                                                                                          [/offtop]
                                                                                    +4
                                                                                    Как можно было, например, написать утилиту:
                                                                                    Заголовок спойлера
                                                                                    package main
                                                                                    
                                                                                    import (
                                                                                    	"fmt"
                                                                                    	"io/ioutil"
                                                                                    	"os"
                                                                                    )
                                                                                    
                                                                                    func main() {
                                                                                    	var err error
                                                                                    	reader := os.Stdin
                                                                                    	if len(os.Args) > 1 {
                                                                                    		if reader, err = os.Open(os.Args[1]); err != nil {
                                                                                    			panic(err)
                                                                                    		}
                                                                                    	}
                                                                                    	text, err := ioutil.ReadAll(reader)
                                                                                    	if err != nil {
                                                                                    		panic(err)
                                                                                    	}
                                                                                    	fmt.Println(string(text))
                                                                                    }
                                                                                    


                                                                                    Насчет «ада копирования». Подобные задачи (как в примере), где нельзя отделаться интерфейсами и приходится копипастить я встречал крайне редко в повседневной практике. Ну и кодогенерацию никто не отменял. В целом, конечно, печально, что нет шаблонов
                                                                                    C зависимостями не все так и плохо. Есть сайт gopkg, на который льют релизы библиотек, есть утилита glide, который может заморозить все библиотеки(сохранив текущие коммиты библиотек в спец файлик), да и сами google уже почти запилили менеджер dep, скоро собираются вносить в свой toolchain
                                                                                    И последнее заявление:
                                                                                    Еще одна скрипучая проблема в том, что Go — это процедурный язык (подобно тихому ужасу Си). В итоге начинаешь писать код в процедурном стиле, который чувствуется архаичным и устаревшим. Я знаю, что объектно-ориентированное программирование — это не серебряная пуля, но это было бы здорово иметь возможность абстрагировать детали в сами типы и обеспечить инкапсуляцию.

                                                                                    Кто же сказал, что go процедурный язык? В чем проблема обеспечить инкапсуляцию? Хоть интерфейсом, хоть просто выносом в другой пакет
                                                                                      +1

                                                                                      Вам доводилось пользоваться кодогенерацией в своих проектах? Довольно муторное, ненадежное и небыстрое занятие. По мне, это сваливание ответственности с компилятора на пользователей, особенно в части гарантий работы.
                                                                                      Стоит в проекте появиться 5-10 активно используемым кодогенераторам и появляется чувство, что он обложен черными ящиками, в которых могут быть ошибки, подчас трудно отлавливаемые — разбирать сгенеренный код бывает нелегко. Вместо одного гарантированного решения задачи с обобщенными типами получается зоопарк из разных пользовательских решений, которые надо поддерживать. Это банально дорого.
                                                                                      Кодогенерация, на мой взгляд, это не решение, скорее затычка "вы так хотели generics — нате!"

                                                                                        +1
                                                                                        Стоит в проекте появиться 5-10 активно используемым кодогенераторам и появляется чувство, что он обложен черными ящиками, в которых могут быть ошибки, подчас трудно отлавливаемые — разбирать сгенеренный код бывает нелегко.
                                                                                        А кто вас заставляет кодогенерировать код, который сложно разбирать?

                                                                                        И 5-10 кодогенераторов — это 5-10 скриптов, которые что-то генерируют или 5-10 типов кодогенераторов (ну там ragel, bison, flex и т.д. и т.п.)? 5-10 типов (каждый со своим языком и описанием) — это уже перебор… собственно Go потому и появился чтобы всякие бесконечные Sawzallы не генерить в бешенных количествах…
                                                                                          0

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

                                                                                            +1

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

                                                                                              +1

                                                                                              Но вы работаете с ними как с частью языка. Про это знают тесты, ide, система проверки кода, компилятор и прочее.А ещё оно неплохо интегрировано в язык. Со сторонней кодогенерацией вроде не так.

                                                                                                0

                                                                                                Зависит от кодогенерации (мы ведь просто о дженериках говорим). Я не настолько хорошо знаю Go, но вроде там есть какой-то инструментарий кодогенерации прямо из коробки. Понятно что, чем сложнее генерация, тем сложнее поддерживать, но вопрос инструментария — это уже частности, я просто говорил, что под капотом разницы нет, в C++ тоже кодогенерация, и программист сгенерированный код не читает, ему приходится пользоваться головой и инструментами, какие есть. Причём и там не всё радужно, шаблонный код часто совсем неподдерживаемый а сообщения об ошибках в шаблонном коде — нечитаемая портянка на весь экран. :)

                                                                                                  +1
                                                                                                  в C++ тоже кодогенерация, и программист сгенерированный код не читает, ему приходится пользоваться головой и инструментами, какие есть. Причём и там не всё радужно, шаблонный код часто read-only а сообщения об ошибках в шаблонном коде — нечитаемая портянка на весь экран.

                                                                                                  Каша из логов шаблонного кода со временем превращается в понятное (пусть и все еще большое) чтиво, сам в это когда-то не верил. Ну и вообще говоря можно получить код с инстанциированными шаблонами (e.g clang -Xclang -ast-print -fsyntax-only ...), вдобавок отладчики уже давно выводят типы

                                                                                                    +2

                                                                                                    Ну, весь вопрос — сколько времени понадобится, чтобы превратилась в понятное чтиво. :) По сути это тоже перенос нагрузки на мозг разработчика. Поддержка тоже местами хромает — в CLion у меня, например, целая куча красного кода из-за С++14, если говорить об IDE.


                                                                                                    Это я всё к тому, что, когда кричат "кодогенерация — плохо, шаблоны — хорошо", обычно забывают, что шаблоны — это та же генерация, только внесённая в стандарт языка и (в лучшем случае) обложенная тулингом.

                                                                                                      0
                                                                                                      Для сравнения возьмите дженерики из c#, нету там всяких танцев с бубном.
                                                                                                        +1
                                                                                                        Каша из логов шаблонного кода со временем превращается в понятное (пусть и все еще большое) чтиво, сам в это когда-то не верил.

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

                                                                                                        вдобавок отладчики уже давно выводят типы

                                                                                                        Это если у вас код таки собрался.
                                                                                                        0
                                                                                                        сообщения об ошибках в шаблонном коде — нечитаемая портянка на весь экран
                                                                                                        С появлением концептов это должно уйти в прошлое.
                                                                                                      0

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

                                                                                                        0
                                                                                                        Ведь, взять например шаблоны в C++ — они фактически тоже генерируют код, просто на лету и он нигде не сохраняется.

                                                                                                        А очень жаль. В нетривиальных случаях хотелось бы, чтобы можно было как-то адекватно это дело подебажить.
                                                                                                          0

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

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

                                                                                                      Неправда ли любопытно: кодогенерация — это рекомендуемый путь, но стоит им пойти и начинаются проблемы.
                                                                                                      Так в прошлом проекте использовались генераторы: msgpack для aerospike, easyjson, для клонирования объектов, локальный типизированный кэш, генератор клиента на основе api. Некоторые проекты использовали большее число.
                                                                                                      Иногда в сгенерированном коде находились ошибки и тут приходится читать этот код. Но кодогенераторы пишут кто во что горазд (в общем-то и понятно — это просто сторонние пакеты, стандарта на них нет) и разбираться в таком хозяйстве долго и дорого.
                                                                                                      Для меня, кодогенерация — это перекладывание ответственности и гарантий с больной головы на здоровую.

                                                                                                        –2
                                                                                                        Для меня, кодогенерация — это перекладывание ответственности и гарантий с больной головы на здоровую.
                                                                                                        А какая альтернатива? Шаблоны? Ну так это то же самое, только ещё хуже. Потому что там всё точно также генерируется — только неявно. Причём в случае с кодогенерацией вы можете увидеть и понять — что происходит просто открыв сгенерированный код. А если при открытии сгенерированного файла у вас IDE сжирает несколько гиг памяти, то сразу возникает вопрос: а оно точно нам нада — то при использовании шаблонов можно заметить что «что-то пошло не так», только обнаружив, что линкеру 16GB памяти не хватает и нужно ставить 32GB только чтобы получить один бинарник на гигабайт…

                                                                                                        Даже на C++ я часто вижу, что люди используют кодогеренрацию, а не шаблоны. Потому что как средство метапрограммирования кодогенерация зачастую — удобнее.
                                                                                                          0
                                                                                                          Дженерики как в хаскеле. Это не шаблоны в смысле плюсов и не template haskell в смысле полноценной компил-тайм-манипуляции AST, а просто реализация наблюдения, что типы данных обычно изоморфны рекурсивным кортежам. Через это можно и хеши делать, и операции сравнения, и вывод на экран, и жсон, и БД, и вообще большую часть того, что надо от кода, претендующего на манипуляции с AST и всяким таким.

                                                                                                          А, ну а вообще полноценной системы типов хватает, когда вы можете написать функцию, которая в своей сигнатуре говорит, что она работает с любым типом, реализующим Ord, например, или вроде того. Это вообще 99% всех использований покрывает.
                                                                                                    +1
                                                                                                    Кто же сказал, что go процедурный язык? В чем проблема обеспечить инкапсуляцию? Хоть интерфейсом, хоть просто выносом в другой пакет

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

                                                                                                      0
                                                                                                      Более того, пример javascript убедительно показывает, что именно инкапсуляция-то в ООП и вовсе оказалась необязательна :-)
                                                                                                        0
                                                                                                        Вы про активное использование штук типа bind?
                                                                                                          0
                                                                                                          Нет, про отсутствие приватных свойств у классов.
                                                                                                            0
                                                                                                            Incapsulation в JS используется, просто всякими Module Design Pattern'ами и прочими трюками с closure'ами.
                                                                                                              0
                                                                                                              Используется-то используется, но не требуется.
                                                                                                              0

                                                                                                              Я слонен разделять инкапсуляцию и сокрытие.

                                                                                                            0

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

                                                                                                        0

                                                                                                        Самым главным в программировании я считаю это умение решать задачи. Для решения задачи есть инструменты, и язык это инструмент, в частности, go тот язык, которым быстро можно овладеть. С моей точки зрения нужно использовать инструмент, который быстрее приведёт вас к решению задачи. Кроме того есть ряд известных преимуществ языка GO, например производительность, в отличие от JAVA.
                                                                                                        Предположим что вы решаете задачу, ту, которую до вас не решал никто, на каком языке она будет решена — неважно, важно что решена, именно это и определяет потенциал человека. Простой пример, это гений Перельман, который блестяще решил теорему Пуанкаре. В вашем же случае, умные программисты — это программисты с завышенным ЧСВ. Или как это сейчас модно, знающие лайфхаки, в языках, из разряда, как сделать чтобы коврик в туалете не уезжал из под ног. Именно этот набор знаний, вы и выдаёте за ум.


                                                                                                        Более 8-ми лет я пишу прошивки под разные микроконтроллеры, и конечно же на си, который я знаю также, как истинные верующие отченаш. Когда нужно организовать простенький сервер, для приема и обработки данных с железки, я часто пользуюсь Go. И здесь вопроси умения возникает мало. Другое дело, когда нужно помочь с реализацией на Java, или Android. Из-за ООП, мне гораздо сложнее, тк мне необходимо продумать по сути архитектуру и структуру классов. Это даётся мне сложнее, но только по тому что это не основной мой навык.

                                                                                                          0
                                                                                                          конечно же на си

                                                                                                          А почему не на ассемблере? Значит для Вас важен язык. Это, на мой взгляд, противоречит Вашим словам:
                                                                                                          на каком языке она будет решена — неважно
                                                                                                            +3

                                                                                                            Си — это и есть кроссжелезочный ассесблер

                                                                                                              +1
                                                                                                              Это как сказать — «питон это кроссжелезный си» =)
                                                                                                              Си потому и придумали, что по отношению к ассемблеру это язык высокого уровня.
                                                                                                                0

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

                                                                                                              0
                                                                                                              Можно и на ассемблере, только у каждой архитектуры свой набор команд. А это время. Если в задача — максимально короткое и эффективное время исполнения (лучше чем скомпилировал бы компилятор си), я использую ассемблер. Сейчас любой компилятор позволяет комбинировать си и асм, опять же для удобства и быстроты реализации задачи.
                                                                                                              Время это очень ценный ресурс.
                                                                                                              Поэтому для меня важно умение решать сложные задачи за максимально короткое время. Поэтому в Go я гораздо быстрее разберусь чем в JAVA
                                                                                                                0
                                                                                                                На С потому что для микроконтроллеров это без вариантов, если вы не хотите заниматься извращениями и нужна хорошая производительность. Не плюсы, потому что ABI нужно дописывать, он платформозависим. Asm для критически-важных (по скорости) секций, хоть это и значит, что запас минимален и кристалл выбран неправильно.
                                                                                                                Да, можно сейчас на LUA писать «прошивки», но когда нужна прямая работа с памятью (записать такой-то бит в ячейку с таким-то адресом), или когда на практике знаешь, зачем нужны volatile-переменные, С просто удобнее.
                                                                                                            0
                                                                                                            Еще одна скрипучая проблема в том, что Go — это процедурный язык (подобно тихому ужасу Си). В итоге начинаешь писать код в процедурном стиле, который чувствуется архаичным и устаревшим. Я знаю, что объектно-ориентированное программирование — это не серебряная пуля, но это было бы здорово иметь возможность абстрагировать детали в сами типы и обеспечить инкапсуляцию.
                                                                                                            Интересно, что и в упомянутой книге (перевод) слово «объект» встречается три раза, а слово «класс» — только два: первый раз не по делу, а второй раз:
                                                                                                            В Go есть несколько различных типов для представления чисел. Вообще, мы
                                                                                                            разделим числа на два различных класса: целые числа и числа с плавающей
                                                                                                            точкой. (С.15)
                                                                                                            Но если верить Википедии, Go — ОО язык (в отличае от Си):
                                                                                                            Специальное ключевое слово для объявления класса в Go отсутствует, но для любого именованного типа, включая структуры и базовые типы вроде int, можно определить методы, так что в смысле ООП все такие типы являются классами.
                                                                                                            Из дальнейшего текста вики видно, что принципы ООП понимаются в этом языке довольно своеобразно.
                                                                                                              +2
                                                                                                              Из дальнейшего текста вики видно, что принципы ООП понимаются в этом языке довольно своеобразно.
                                                                                                              Они понимаются примерно как в CLOS. Который является вполне себе ООП-языком — и гораздо более гибким, чем C++/C#/Java…
                                                                                                              +2
                                                                                                              Вот взять например язык для «умных» и выразить вторую задачу:
                                                                                                              putStrLn $ show $ foldl1 (+) [1, 2, 3.3]
                                                                                                              

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

                                                                                                              Хорошо решим первую задачу:
                                                                                                              import System.Environment
                                                                                                              import Data.Char
                                                                                                              main = getArgs >>= printFile
                                                                                                                  where printFile (x:_) = readFile x >>= putStr
                                                                                                                             printFile [] = getContents >>= 
                                                                                                                                 readFile . filter (not . isControl) >>= 
                                                                                                                                     putStr
                                                                                                              

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

                                                                                                                Первый пример крайне просто читается, даже человеком со знанием английского (при условии, что он догадается, что str -> string и foldl -> fold).
                                                                                                                Второе уже требует знания монад и ФП, тогда не должно являться большой проблемой.


                                                                                                                А что касается времени на написание — то ФП, это, по моему опыту, совсем другие дебри. "Что-то накидать хоть немного работающее и сделать это быстро" — явно не про оное. Так что думаю сравнение не очень уместно. Впрочем, мой опыт может быть и не столь обширен

                                                                                                                  +1
                                                                                                                  Ну, мой опыт с вашим не согласен. Как раз быстро накидать что-то немного работающее получается быстрее на нём.
                                                                                                                  0
                                                                                                                  Зачем foldl1 (+), когда есть sum, который уже давно работает поверх произвольного Foldable?

                                                                                                                  И я бы второй пример переструктурировал немножко:
                                                                                                                  main = getArgs >>= file >>= readFile >>= putStr
                                                                                                                      where file (x:_) = pure x
                                                                                                                            file [] = filter (not . isControl) <$> getContents
                                                                                                                  
                                                                                                                    +1
                                                                                                                    Да вариант действительно отличный. Только сколько людей могут предложить такой вариант? Сколько людей знают что такое аппликативный функтор и что монада тоже им является? А в статье написано сел и за один вечер освоил, быстро накидал и в продакшн (((
                                                                                                                    main = do
                                                                                                                        args <- getArgs
                                                                                                                        stdIn <- getContents
                                                                                                                        let file = if null args
                                                                                                                                        then filter (not . isControl) stdIn
                                                                                                                                        else head args
                                                                                                                        content <- readFile file
                                                                                                                        putStr content
                                                                                                                    

                                                                                                                    Я использовал do нотацию как мог, чтобы упростить. Правда похоже на императивный код? Я его за минуту написал, а над прошлым вариантом задумался, хотя он много лучше
                                                                                                                      +1
                                                                                                                      Только сколько людей могут предложить такой вариант?

                                                                                                                      Всё дело в эстетике :) У вас вот putStr в обоих ветвях повторяется, поэтому естественный вопрос: а можно ли его как-то оттуда вынести и обобщить, например? Вынесли, теперь readFile повторяется. И так далее.

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

                                                                                                                      Любой, кто знает, что такое монада (когда я только изучал хаскель во времена ghc 6 и задолго до applicative/monad proposal, равно как и задолго до моего упарывания теоркатом, помню, сильно удивлялся, почему Monad не является субклассом Applicative). Но да, я согласен, таких людей меньше, чем программистов на Go.

                                                                                                                      А в статье написано сел и за один вечер освоил, быстро накидал и в продакшн (((

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

                                                                                                                        Ребят, а как такое тестировать?

                                                                                                                          +4
                                                                                                                          А что именно тут тестировать?
                                                                                                                            +5
                                                                                                                            Никак, люди так пищущие — не допускают ошибок
                                                                                                                              +1

                                                                                                                              Ну-ну. Самоуверенные и самовлюбленные нарциссы.


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

                                                                                                                                +2
                                                                                                                                Эх, неужели это было слишком тонко?
                                                                                                                                  –1

                                                                                                                                  Ну… с учетом того, что меня заминусили, было тонко, да)

                                                                                                                                  +1
                                                                                                                                  Я тестирую свой код, написание в стиле комментария на пару уровней вверх этому не мешает. Просто тестируется чуть более широкий набор функциональности сразу.

                                                                                                                                  Реально, что там тестировать-то? :)
                                                                                                                        +15
                                                                                                                        Go изначально разрабатывался для того, чтобы переписать тормознутые сервисы на python/php/perl, и не отстрелить себе ноги на (C/C++). Что этот язык и сделал. То, что из него стали делать вундервафлю под все задачи (как это в свое время делали из node.js) — просто хайп.

                                                                                                                        Что касается сравнения GO с другими языками, в частности Java, то Google разработала Go и начала его активно использовать, чтобы отказаться от зависимости от Oracle. Заметьте одну вещь.

                                                                                                                        • Oracle — Java
                                                                                                                        • Microsoft — C#
                                                                                                                        • Google — Go
                                                                                                                        • Facebook — php (php Hack)
                                                                                                                        • Apple — Object-C/Swift


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

                                                                                                                        Сейчас Google замкнет всю свою систему на GO и станет таким же вендор локом, как и Microsoft, как Apple и прочее =)
                                                                                                                          +1

                                                                                                                          Можно ли дополнить список Mozilla с её Rust? Кажется, новые языки создают все кто может.

                                                                                                                            +5

                                                                                                                            У go не получилось в этом смысле — проект go-mobile скорее мертвый, чем живой, и сам Google для мобильной разработки советует Kotlin.

                                                                                                                              –6
                                                                                                                              Устарело.
                                                                                                                              Гугл для мобильной разработки советует Dart
                                                                                                                                +1
                                                                                                                                Ок, скажем тогда иначе, «что угодно, но не go-mobile».
                                                                                                                                  +5
                                                                                                                                  Где и кому они такое советуют?
                                                                                                                                    0

                                                                                                                                    можно по подробней?

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

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


                                                                                                                                К тому же, потребность в своём собственном языке никак не влияет на дизайн этого языка. Задачи Google не так сильно отличаются от задач тысяч других компаний — (микро)сервисы с максимальной утилизацией CPU и памяти. Это объясняет горутины, например. Стремление к простоте изучения и близости к C тоже понятна, учитывая тысячи работающих у них студентов, хотя для многих других компаний это свойство языка может быть совершенно ненужным или неуместным. А вот замена дженериков на кодогенерацию или использование зависимостей без чёткого версионирования лично для меня ну совсем непонятны.

                                                                                                                                  0
                                                                                                                                  использование зависимостей без чёткого версионирования
                                                                                                                                  Для лучшего понимания можете глянуть, например, доклад Why Google Stores Billions of Lines of Code in a Single Repository. Там и про кодогенерацию вскользь упоминают.
                                                                                                                                    0

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

                                                                                                                                      0
                                                                                                                                      Пожалуй так. Подчеркну, что речь не просто про монорепу, а еще про trunk based development.

                                                                                                                                      Выходит, что сама концепция «версионирование зависимостей» становится лишней (в том числе для других языков, вроде Java или Python). А разработчикам Go просто не было смысла тратить много времени на ее проектирование и реализацию. Посему и сделали максимально просто (скорее даже примитивно).
                                                                                                                                        +5

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

                                                                                                                                +6
                                                                                                                                Отлично! Как-раз искал что-то вроде С для дураков. Ещё и с книжкой сразу. Спасибо!
                                                                                                                                  +1
                                                                                                                                  Если нужна книжка по Go — смотрите в сторону Кернигана (а вот его сишную лучше не читать).
                                                                                                                                    0

                                                                                                                                    Спасибо! А библиотеку для обмазывания цветом и рамочками вывода в консоль какую лучше использовать?

                                                                                                                                      0
                                                                                                                                      Если я вас правильно понял, то вы хотите ncurses для Go. Так вот, его нет. Попытки были, но когда я пробовал — всё было не оч. Если сильно хочется некомандный интерфейс, то стоит смотреть в сторону http. Серьёзно, 5 минут делов, всё необходимое уже есть в стандартной библиотеке, нет проблем с переносимостью. Если не устраивает — стоит спросить другие варианты у коллективного разума в русском Go Slack сообществе.
                                                                                                                                        0
                                                                                                                                        Спасибо! Попробую непременно оба совета.
                                                                                                                                        0
                                                                                                                                        +1
                                                                                                                                        А что не так с сишной?
                                                                                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                                        +1
                                                                                                                                        print while(<>);
                                                                                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                                            0

                                                                                                                                            Достаточно скрипта только из комментария:


                                                                                                                                            #!/usr/bin/perl -p

                                                                                                                                            или даже пустого perl-скрипта (дзен-вариант) :)


                                                                                                                                            echo 123 | perl -pe ""