Go исполнилось 5 лет

    image

    В своем посте, посвященному праздничному событию, один из создателей языка Andrew Gerrand вспоминает то, как прошли эти годы и как все было пять лет назад. Вот так тогда выглядел официальный сайт; сами авторы Go называли его «системным языком», каждую строчку кода надо было заканчивать точкой с запятой, для сборки своих приложений приходилось писать мейкфайлы — и будущее языка было покрыто мраком. Сразу после релиза «язык от Google» привлек широкое внимание, после чего основная волна быстро схлынула, не увидев в языке ничего нового. Те немногие, кто увидел в языке будущее, сформировали «ядро» команды его разработчиков, и вышедшая в 2012 году первая версия языка была серьезным достижением, благодаря которому на сегодняшний день в развитии языка и экосистемы вокруг него решили принять участие сотни программистов.

    Помимо «праздничного» поста, интерес представляет опубликованная расшифровка недавнего выступления Брэда Фицпатрика про настоящее и будущее Go. Официально Брэд — создатель memcached, OpenID и LiveJournal — занимается разработкой Camlistore, но по ходу дела ему приходится часто заглядывать в исходники Go и добавлять необходимый для Camlistore функционал в библиотеки языка или фиксить баги.
    image
    Итак, относительно будущего языка. Go 1.4 включит в себя несколько новых фич и багфиксов, при этом заложив основу для low-latency сборщика мусора и возможности запуска Go на мобильных платформах. Версия 1.4 уже вышла в первую бету, релиз выйдет 1 декабря.

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

    Про Go 2.0 задумываться пока еще рано — по крайней мере потому, что разработчики пока не решили, что можно и нужно будет «сломать», поэтому второй версии нет еще даже в планах. Поэтому о том, что последует за версией 1.5, мы узнаем уже в следующие 5 лет — а в качестве праздничного подарка в блоге Gopher Academy в этом месяце будет опубликована серия статей от известных гоферов.
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 41
      +2
      Радует, что Go развивается, да и сообщество гоферов (в том числе и у нас) растет. Честно говоря еще пару лет назад думал, что язык наполовину мертв.
        0
        Кстати, есть ли в России организации, ведущие разработку на Go, если не всю, то хотя бы частично?
        Язык очень красивый, рад за него всем сердцем. Эй, с днём рождения, Go!
          0
          Конечно есть, например Яндекс использует его для бэкэнда своего браузера.
            +3
            Мы частично используем (компания «Системы документооборота», система документооборота «Практика»).
              0
              У нас (lori.ru) некоторое количество мелких сервисов на Го. В частности, сервисы, обрабатывающие картинки. Правда, к сожалению, родная картиночная библиотека Го очень медленная, приходится использовать биндинг к ImageMagick.

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

              Вообще, язык классный, очень легко на нём писать, и результат получается весьма надёжным. Хотя генериков и не хватает:)
                0
                Badoo активно использует Go. И мучается с GC…
              +11
              опередили с новинками в 1.4
              если позволите пару комментариев и дополнений:
              — не многопоточный, а параллельно выполняющийся, он планируется в 1 потоке, также для этого в 1.4 запись всех указателей сделали через внутреннюю функцию, которая может эту самую запись блокировать по желанию GC
              — Большая часть runtime была переписана на Go, это позволило уменьшить размер кучи от 10% до 30% за счет работы сборщика мусора, а для каждой горутины в 4 раза уменьшить начальный размер стека (с 8192 до 2048 байт), правда к релизу это значение может быть установлено в 4096 байт (имхо так и будет, все таки размер страницы памяти на большинстве систем по умолчанию именно такой)
              — приватные пакеты — теперь можно создать пакет который не будет являться частью публичного api, например пакет src/mypkg/internal/foo будет доступен только для пакета src/mypkg. Пока это изменение доступно только для стандартной библиотеки языка, а для сторонних пакетов обещают включить в 1.5
              — для стандартизации кодогенерации добавлена команда go generate. При помощи специальных комментариев вы можете указать какие команды необходимо запускать. Но делать как и раньше это придется руками и сохранять созданные файлы в репозиторий пакета (отсутствие автоматического запуска сделано намеренно)
              — каноническое название пакета, теперь с помощью комментария рядом с названием пакета можно указать правильный вариант импорта пакета, это поможет избегать дублирования если пакеты импортируются с разными путями (например github.com/my/pkg и my/pkg)

              package pdf // import "rsc.io/pdf"
              

              + несколько изменений поменьше, подробнее Go 1.4 Release Notes (англ.)
                0
                Вам спасибо за интересный комментарий, я-то в посте всего лишь шапочно пробежался по роадмапу. Про GC поправил.
                +2
                Чисто гипотетически, реально ли на Go переписать Андроид? Слышал, что у гугла были проблемы с ораклом из-за джавы, да и вроде Go рассчитан на многопроцессорную архитектуру, к коим устремлены современные смарты.Вроде как ништяк получился бы. Объясните неспециалисту
                  0
                  Переписать весь Android это вряд ли, тем более что он написан не на Java. А вот приложения вы можете уже сейчас писать на C/C++ с помощью Android NDK. В Go 1.4 должна появиться поддержка Android NDK, так что можно будет начинать его потихоньку использовать.
                    0
                    java (dalvik) это платформонезависимый байт код, который выполнится на любом устройстве, в Go нет виртуальной машины и придется создавать исполняемые файл под все платформы (процессоры). Уже есть много софта который написан на java. Ну и грузить все ядра на мобильнике — это только для игрушек и бенчмарков. Так что Go и Java для разного, а вот рассматривать Go как язык для 3D игр очень даже. По сути по скорости он проигрывает C в обработке бинарных данных (например декодирование изображений 2-3 раза) из-за того что все операции в GO проверяются (границы массива и т.п.) и если вы в это упретесь всегда можно написать часть кода на C
                      –2
                      А есть смысл? С точки зрения производительности языки и их реализации ведь довольно близкие, теперь даже AOT есть в art.
                      +2
                      Поздравляю! Ура!
                      \(^-^)/
                        0
                        Мысли вслух

                        Хейтеры, как правило, к основным недостаткам Go относят отсутствие генериков и обработка ошибок.
                        Вот лично мне генериков не хватает, так как interface{} все-таки не такой шустрый как хотелось бы, а ошибки — ну, жить вполне себе можно с тем, как сделано сейчас.

                        К альтернативам относят Rust и OCaml. Первый не пробовал, на втором мне достаточно сложно писать. Честно пытался, прочитал книгу, все равно не цепляет, как основной язык разработки
                          0
                          Как адепта всяких хаскеллей, для меня тоже раньше было краеугольпым камнем отсутствие генериков. Но потом я понял, что в языке комфортнее всего, когда есть некий компромисс, между строгим статическим и абсолютным динамическим. Поиск этого компромисса — не простая задача для тех, кто стал на путь дизайна новых языков.

                          Мысли вслух
                            0
                            в Rust также нет исключений, из плюсов там есть макрос ifError, тоесть
                            // вместо 
                            if err != nil {
                                return err
                            }
                            
                            // такое
                            ifError(err)
                            

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

                            а по поводу interface{} — если не секрет, что вы делали что ощутили «не шустрость»?,
                            в моих кейсах например вместо container/list сделать свой (с указателем вместо Value interface{}) то выигрыш от отказа от интерфейса получается порядка 10-7 на операцию вставки (на получении чуть меньше). т.е. на 10кк элементах выигрыш 1 секунда.
                              +3
                              Не нашел никаких упоминаний макроса ifError в Rust. Вероятно его убрали.
                              Отличия обработки ошибок в Go и Rust состоят в основном в том, что в Rust есть Pattern matching + стандартная функция unwarp.

                              Для примера возьмем функцию, которая может вернуть ошибку(в виде кортежа в случае с Go, в виде типа Option в случае Rust): конвертация строки в число.

                              Go:

                              Игнорируем ошибку:
                              n, _ := strconv.Atoi("123")
                              

                              Падение при некорректной строке
                              n, err := strconv.Atoi("123")
                              if err != nil {
                                  panic(err)
                              }
                              

                              Обработка ошибки:
                              n, err := strconv.Atoi("123")
                              if err != nil {
                                  ...
                              }
                              


                              Rust:

                              Падение при некорректной строке:
                              let n = from_str::<u64>("123".as_slice()).unwrap();
                              


                              Обработка:
                              match from_str::<u64>("123".as_slice()) {
                                      Some(n) => { ... }
                                      None => { ... }
                                  }
                              


                              Как в Rust совсем проигнорировать ошибку и иметь при этом возможность обратиться к переменной 'n' я не придумал.

                              Rust заставляет либо проверять ошибку, либо ронять поток выполнения в случае ошибки(Option.unwrap(error) делает panic!(error) в случае, если значение — None)

                              Go позволяет случайно(или из-за плохого стиля кодирования) пропустить обработку реальной ошибки(первый вариант) и продолжить исполнение программы на некорректных данных.
                                +1
                                В смысле, «случайно»? То есть вы считаете, что можно случайно поставить запятую и подчёркивание после переменной n?

                                Такие вещи можно сделать только специально и это действительно сразу видно. В этом большой плюс. Потому как задачу воспитания у молодёжи best practices никто не отменял…
                                  0
                                  это я не правильно написал — в Rust это try! (статья в тему habrahabr.ru/post/242269/)
                                  ifError в Go у нас было в паре проектов, но так как это не макрос там как раз вариант с panic
                                0
                                Интересно, почему Rust?
                                Мне кажется, что у Rust совсем другая ниша, чем у Go.
                                  0
                                  Не так много на рынке статически типизированных, компилируемых в нативные бинарники, кроссплатформенных, да ещё и сколько-нибудь распространённых языков. Если не брать си с плюсами, то останется, по сути, только OCaml, Go и Rust.
                                    –3
                                    Ну .net умеет компилиться теперь в бинарники. С кроссплатформенностью хуже.
                                    Непонятно откуда требование компилиться обязательно в бинарники. Я бы ставил требования типа «удобный GUI», «нормальная производительность».
                                      +2
                                      А во что ещё? Можно интерпретировать, но даже с JIT-ом интерпретация медленна (хотя вот Lua неплохо справляется). Можно создавать код для вирт. машины (Java и вся её семья), но это требует поддержки собственно виртуальной машины, нетривиальной её настройки и обычно большого кол-ва памяти. И можно компилить в бинарники, которые запускаешь, и они работают. Особенно удобны Go-бинарники в силу статической линковки — деплой сводится к копированию ровно одного файла.

                                      Разумеется, можно убрать требование компиляции, и тогда спектр языков станет гораздо шире. Но тем, кто выбирает Go, обычно компиляция важна.
                                        –1
                                        Все-таки, выбирать способ линковки — предпочтительней.
                                          0
                                          Они сейчас работают над этим. И чтобы отдельные библиотеки (.dll, .so…) можно было на Go писать.
                                  +1
                                  Я мало встречал людей пописавших на Go и страдающих от отсутствия generic'ов. Генерики — это модная практика, которая тем не менее имеет свои недостатки.
                                  Я пока что не сталкивался с ситуациями когда отсутствие отсутствие генериков на Go вызывало дискомфорт.
                                    0
                                    Вот отличная статья Алексея Качаева про то, когда начинают быть нужны генерики: gist.github.com/kachayev/21e7fe149bc5ae0bd878 (на английском).

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

                                      Promise и PubSub'ы — это суровая необходимость javascript, вызванная его принципиально асинхронной природой. Имитировать их в Go нет никакой необходимости. Понятно, что когда ты с помощью молотка, пытаешься резать торт, то получается не очень…

                                      Когда я осваиваю новый язык, следующим этапом после изучения синтаксиса, а читаю style guide и best practices. Это очень хорошо помогает въехать в стиль разработки принятый на конкретном языке…
                                        –1
                                        Одной из идеоматических бест-практик Го являются каналы каналов — когда мы передаём канал Б в канал А и слушаем из канала Б результат. Если внимательно посмотреть на этот паттерн, то можно увидеть обыкновенный Promise. Но нам ведь обычно не интересно передавать _только_ каналы. Нам интересно передать данные какого-то типа, и получить через обратный канал данные какого-то другого типа. А ещё и ошибки хорошо было бы получать. Сейчас это всё можно делать только через interface{} или через копипаст. Хотя передавать в канал канал для результата — это то, чем начинается каждый учебник Го, идеоматичнее паттерна и быть не может.

                                        На PubSub Алексей там тоже сослался — о нём рассказывается непосредственно в пайковском “Advanced Go Concurrency Patterns” (http://blog.golang.org/advanced-go-concurrency-patterns). Если это не best practice, то и не знаю, что тогда best practice.

                                        Я давно пишу на Го, и он мне очень нравится и без генериков (я без них не «страдаю»). Однако я вижу, что с генериками мы могли бы получить более мощные библиотеки.
                                          0
                                          сейчас никто не мешает использовать кодогенерацию для разного рода рутины (например для сериализации/десериализации) и т.п., шаблоны в Go можно делать также, далее абстрактный пример:
                                          в библиотеке объявляете свой тип и в методах его принимаете/возвращаете, там где нужно использовать пишите:
                                          // `template:"github.com/user/mylib.type"`
                                          type myType ...
                                          


                                          запускаете генерацию получаете файлик с суфиксом _gen и все работает.

                                          вот пример подобного github.com/clipperhouse/gen
                                            0
                                            Да, есть много вариантов кодогенерации (я этим вопросом интересовался). Есть даже крутая идея генериков-как-веб-вервиса:) — bouk.co/blog/idiomatic-generics-in-go/

                                            К сожалению, это очень ограниченное решение. Простой пример: есть некая библиотека list, реализующая, скажем, типизированный список: list.List (просто для примера). Пусть теперь в _нашем_ пакете user есть тип user.User и мы хотим в нём же использовать user.List. Кодогенерацией это сделать невозможно — чтобы сгенерировать код для List, нам надо в сгенерированный пакет импортировать пакет user, а потом то что получилось импортировать в user же. Получится циклический импорт.

                                              0
                                              (сорри, в первом варианте комментария парсер съел угловые скобки)

                                              …Простой пример: есть некая библиотека list, реализующая, скажем, типизированный список: list.List[T] (просто для примера). Пусть теперь в _нашем_ пакете user есть тип user.User и мы хотим в нём же использовать user.List[user.User]. Кодогенерацией это сделать невозможно — чтобы сгенерировать код для List[User], нам надо в сгенерированный пакет импортировать пакет user, а потом то что получилось импортировать в user же. Получится циклический импорт.
                                                0
                                                что-то я видимо не понял примера, у вас оба типа в одном пакете, вы делаете тип usersList, реализация которого выполняется генерацией кода из шаблона который в пакете list получается файлик users_list_gen.go который сохраняется в вашем пакете user. То есть это тоже самое что вы бы сделали usersList с 0, только вам код не пришлось писать
                                                  0
                                                  Сорри, пример плох тем, что List пересекается с тем, что предлагает 'gen'. Там действительно генерится один файл, и нет проблем со встраиванием в пакет.

                                                  Но если List (или какая-то другая нетривиальная структура) требует не одного файла, а целого пакета, возможно, с подпакетами и импортами снаружи — вот как в таком случае генерировать код, я не знаю…
                                    0
                                    Меня печалит отсутствие стабильной библиотеки для GUI. Go-qml банально []string как модель принять не может, а в go-ui вообще нет такого контрола как ComboBox. Go-gtk мало того что не развивается, так и толком скомпилить не получается…
                                    Может посоветуете еще чего для кроссплатформенной морды?
                                      0
                                      wxWidgets пробовали?
                                        0
                                        О, сеньк, посмотрю, что-то пропустил.
                                        0
                                        > банально []string как модель принять не может
                                        «Это временные трудности на пути к царству света!»

                                        Самый адекватный хак здесь это сделать метод func At(i int) string, тогда можно будет использовать как модель длину слайса, а внутри элемента модели через .At(index) получить искомую строку. Так можно слайс любых объектов завернуть.
                                        Если не очевидно, могу пример привести.
                                          0
                                          Да, пожалуйста. То есть я понял, что надо воспроизвести методы, которые qml ждет от модели и которых нету у слайса, но мне казалось, что оно падало в момент присвоения прям с каким-то мессагом типа «connect with developers»
                                            0
                                            Нет, там никто не ждет методы, вот пример с делегатом github.com/go-qml/qml/tree/v1/examples/modelview/delegate
                                            то же самое, когда вы делаете Component для ListView.
                                              0
                                              О, спасибо! Все-таки я предпочту Qt всему остальному.

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

                                      Самое читаемое