Кто такой Go-разработчик и как им стать

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

В 2009 году разработчики Google представили Go — язык программирования, который совместил простоту разработки на Python и скорость C++. Сейчас на нём уже написано множество сервисов, например, Docker и Kubernetes. Язык продолжает активно развиваться и завоёвывать позиции среди сообщества разработчиков. А ещё освоить его может даже новичок.

Разбираемся, за что программисты любят Go и какие задачи он помогает решать. В этом помогут Георгий Зуйков, техлид курса «Go-разработчик», старший разработчик в «Едадиле» и член Go-комитета Яндекса, а также Дмитрий Шубенок, тимлид авторов курса «Go-разработчик».

Подробнее про Go

Go — это высокоуровневый язык программирования, который задумывался для быстрого написания микросервисов. Язык строго типизированный, то есть каждая переменная имеет свой тип, который нельзя менять. Его придумали в Google в качестве замены С++ на тех проектах, где была важна скорость разработки и компиляции кода. Go — простой язык: в нём мало ключевых слов и неявных элементов. Основной упор сделан на эффективное использование вычислительных ресурсов при минимальных затратах и на написание кода благодаря встроенным в язык примитивам многопоточности.

На Go можно программировать всё что угодно. В языке есть небольшой набор ключевых слов, но работают они как конструктор. Здесь нет никаких подводных камней: если написано слово interface, это означает, что оно относится именно к интерфейсу приложения. Кстати, в этом одно из преимуществ Go перед C++: если в последнем обнаруживается какая-то проблема, то разработчики языка добавляют новое ключевое слово или составляют хитрые конструкции из старых слов. Отсюда часто возникает путаница в коде.

Go популярен среди разработчиков: по данным TIOBE Index, он входит в топ-20 самых используемых языков, а в рейтинге GitHub занимает четвёртое место. Несмотря на «подростковый» возраст языка — в ноябре 2021 года ему исполнилось двенадцать лет, его можно считать достаточно зрелым и состоявшимся. На Go уже написано огромное количество проектов. Одни из самых популярных — инструменты для контейнеризации Docker и оркестрации контейнеров Kubernetes. Помимо этого есть много DevOps-инструментов для аналитики и сбора данных, например, Prometheus или Grafana. Ещё Go часто используют для проектов в больших компаниях. Разработчики Uber применяют Go в инфраструктуре продуктов и выкладывают много интересных решений в свободный доступ.

Достоинства и недостатки Go

У всего есть свои плюсы и минусы — и Go не исключение. Рассмотрим их с точки зрения практического опыта.

37

Теперь давайте расскажем немного подробнее. Начнём с достоинств.

Простота языка. За счёт своего объёма Go считается самым простым типизированным языком. В нём меньше пятидесяти ключевых слов, и при этом разработчики следят за тем, чтобы в языке без надобности не появлялись новые непонятные конструкции. Например, в свежей версии 1.18, которая выйдет в феврале 2022, появится первое изменение языка за 12 лет — это будет новая конструкция типизированных параметров.

Как пример — в Go для любых итераций используется только одно ключевое слово for.

sum := 0
for i := 1; i < 5; i++ {
    sum += i
}
fmt.Println(sum) // 10 (1+2+3+4)

Больше примеров паттернов циклов в Gо

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

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

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

Запустить горутину так же просто, как и вызвать функцию: нужно поставить ключевое слово go перед вызовом.

func main() {
    go sleepyGopher() // Начало горутины
    time.Sleep(4 * time.Second) // Ожидание
} // Здесь все горутины останавливаются 

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

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

c := make(chan int)

Самодостаточность. Go компилируется статически. То есть когда разработчик написал программу и скомпилировал её, то она поместится в один бинарник, в котором прописаны все зависимости. Это позволяет переносить его на любой компьютер с той же операционной системой: с Linux на Linux, с Mac на Mac или с Windows на Windows. Если писать на Python или C++, нужно позаботиться о множестве дополнительных файлов — например, об интерпретаторах и библиотеках.

Активное развитие. Отдельно хочется отметить интересную особенность Go — это Backward Compatibility Promise. Суть такая: разработчики языка заявили, что все версии Go будут обратно совместимы. Другими словами, любой код, который был написан для предыдущих версий Go, будет обрабатываться всеми новыми. Именно поэтому у новых версий Go высокий adoption rate.

Теперь перейдём к недостаткам. Местами они могут быть субъективными, но при этом передают опыт работы с языком.

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

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

Так это выглядит в сравнении с Java и C:

37

А так выглядит код:

input := "2017-08-31"
layout := "2006-01-02"
t, _ := time.Parse(layout, input)
fmt.Println(t)                       // 2017-08-31 00:00:00 +0000 UTC
fmt.Println(t.Format("02-Jan-2006")) // 31-Aug-2017

Иногда в языке не хватает того, что в Python называется «батарейки» — это отдельные элементы стандартной библиотеки, в которых есть всё для решения распространённых задач. В Go, например, нет встроенных базовых структур типа decimal и удобных функций для работы с массивами. Во многом это связано с тем, что язык достаточно молодой и ещё не успел обрасти подобными инструментами.

Нет тернарных операторов. В Go нет возможности одной строкой проверить, является ли элемент true или false.

Например, так выглядит эта проверка на PHP:

$isAdmin = $user->role == "admin" ? true : false;

А так нужно писать то же самое на Go:

var isAdmin bool
if user.Role == "admin" {
    isAdmin = true
}

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

Небольшая замусоренность. Этот недостаток связан с Backward Compatibility Promise, который упоминался в плюсах языка. Из-за сохранения обратной совместимости в языке образуется определённое количество мусора. Если разработчики понимают, что они плохо написали какую-то функцию или в стандартной библиотеке появилась какая-то новая единица, им приходится писать новые функции, которые похожи на старые, но при этом учитывают новые фичи. Получается, что в Go можно встретить две функции, которые делают похожие вещи и даже похоже называются, но при этом старую нельзя выкинуть, ведь где-то может быть код, который использует именно эту функцию.

Чем ещё удобен Go

В основном всё, что нужно писать многопоточно, проще писать на Go — у него есть много примитивов для обработки таких задач. В языке удобно работать с HTTP, на нём можно быстро создавать API, а также мелкий портативный тулинг. Но чаще всего его используют для разработки серверных приложений и сервисов, где есть сложные вычисления, многопоточные системы, парсеры.

Язык статически линкованный: после компиляции у разработчика на руках есть один бинарник без всяких зависимостей. Давайте на примере: разработчик написал небольшую утилиту, которая считает количество указанных слов. На вход отдаётся текстовый файл, а в итоге программа выдаёт число или частотный анализ. После компиляции готового кода получается один бинарник — и это маленький файл на 10–15 МБ. Теперь разработчик может просто передать его через мессенджер или почту, а получатель может открыть бинарник на своём компьютере и пользоваться им без установки дополнительных библиотек.

Что нужно, чтобы начать писать на Go

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

Намного проще будет тем, кто имел дело с С-подобными языками: C++, Python, Java, PHP. Они все примерно похожи по своей механике и типам данных. Но, повторимся, это необязательно: иногда проще начинать именно с Go, чтобы впоследствии перейти на другие языки.

Как обучиться Go

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

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

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

Сейчас «Go-разработчик» рассчитан на специалистов уровня junior+. Но мы планируем расширить его и готовим программы обучения до уровня middle и для тех, кто только начал свой путь в разработке.

Что посмотреть и почитать

Документация по Go

Репозиторий Golang на GitHub

Сайт Go by Example с примерами кода на Go

Статья о типичных ошибках начинающих Go-разработчиков

Краткий пересказ от Yandex GPT