Введение в язык Go
Go представляет компилируемый статически типизированный язык программирования от компании Google. Язык Go предназначен для создания различного рода приложений, но прежде всего это веб-сервисы и клиент-серверные приложения. Хотя также язык обладает возможностями по работе с графикой, низкоуровневыми возможностями и т.д.
Работа над языком Go началась в 2007 в недрах компании Google. Одним из авторов является Кен Томпсон, который, к слову, является и одним из авторов языка Си (наряду с Денисом Ритчи). 10 ноября 2009 года язык был анонсирован, а в марте 2012 года вышла версия 1.0. При этом язык продолжает развиваться. Текущей версией на момент написания данной статьи является версия 1.20, которая вышла в феврале 2023 года.
Язык Go развивается как open source, то есть представляет поект с открытым исходным кодом, и все его коды и компилятор можно найти и использовать бесплатно. Официальный сайт проекта — https://go.dev/, где можно много полезной информации о языке.
Go является кроссплатформенным, он позволяет создавать программы под различные операционные системы — Windows, Mac OS, Linux, FreeBSD. Код обладает переносимостью: программы, написанные для одной из этих операционных систем, могут быть легко с перекомпиляцией перенесены на другую ОС.
Основные особенности языка Go:
- компилируемый — компилятор транслирует программу на Go в машинный код, понятный для определенной платформы
- статически типизированный
- присутствует сборщик мусора, который автоматически очищает память
- поддержка работы с сетевыми протоколами
- поддержка многопоточности и параллельного программирования
В настоящее время Go находит широкое применение в различных сферах. В частности, среди известных проектов, которые применяют Go, можно найти следующие: Google, Dropbox, Netflix, Kubernetes, Docker, Twitch, Uber, CloudFlare и ряд других.
Что нужно для работы с Go? Прежде всего необходим текстовый редактор для набора кода и компилятор для преобразования кода в исполняемый файл. Также можно использовать специальные интегрированные среды разработки (IDE), которые поддерживают Go, например, GoLand от компании JetBrains. Существуют плагины для Go для других IDE, в частности, IntelliJ IDEA и Netbeans.
Установка компилятора
Пакет для установки компилятора можно загрузить с официального сайта https://go.dev/dl/.

По этому адресу пакеты установщиков для различных операционных систем. Так, при загрузки и запуске установщика для Windows открывается следующее окно:

После принятия лицензионного соглашения отобразится окно для выбора места установки:

На Windows, например, по умолчанию используется путь «C:\Program Files\Go\». Оставим путь по умолчанию и перейдем к следующему окну, на котором нажмем на кнопку Install:

После успешной установки в папке установки будут установлены все файлы, необходимые для работы с Go. В частности, в подкаталоге bin можно найти файл go (go.exe на Windows), который выполняет роль компилятора:

После установки мы можем проверить версию языка, запустив следующую команду в консоли/командной строке:
Язык программирования Go: почему все его любят и что на нем можно писать

Go — молодой язык программирования с открытым исходным кодом и огромным комьюнити опытных разработчиков, которые его активно используют. Go создавался в качестве более эффективной, простой и доступной альтернативы другим языкам программирования внутри компании Google в 2007 году.
Тогда Google активно развивался, в том числе и увеличивалось количество кода, который используется для управления инфраструктурой. В итоге работа программ постоянно становилась медленнее, а поддерживать их код было все сложнее и сложнее. Поэтому облачные инженеры в Google пришли к выводу, что им проще придумать новый язык программирования и перенести на него все легаси, чем постоянно оптимизировать весь код. Плюс это позволило бы иметь язык с производительностью как в С, но при этом на котором легко можно писать код.
Один из создателей Go разработчик Роб Пайк говорил, что новый язык программирования должен быть похож на С, C++ или Java — чтобы разработчикам не пришлось сильно переучиваться. Но при этом он должен быть проще, быстрее и эффективнее — потому что сотрудники Google в первую очередь инженеры, а не ученые, которые могут тратить сотни часов на изучение технологии.
Go разрабатывался как опен-сорс проект и публично вышел в 2012 году. За 10 лет он стал одним из самых популярных языков программирования: в 2022 году он находится на шестом месте по популярности среди языков программирования, которые используются на GitHub, обогнав PHP, C, C#, Ruby и Swift.

Бесплатные курсы по программированию в Хекслете
- Освойте азы современных языков программирования
- Изучите работу с Git и командной строкой
- Выберите себе профессию или улучшите навыки

Для чего используется Go
Изначально Go создавался для программ, связанных с сетями и инфраструктурой, в качестве замены популярных высокопроизводительных серверных языков, таких как Java и C++. Сегодня же Go используется как бэкенд-язык для огромного количества различных направлений разработки:
- Облачные и серверные приложения, веб-сервисы
- DevOps и автоматизация процессов
- Приложения для работы с командной строкой
- Искусственный интеллект и работа с большими данными
- Программирование микроконтроллеров и робототехники.
Однако лучше всего Go раскрывается как язык программирования для работы с инфраструктурой. Самые популярные инструменты в этой области написаны именно на Go — Kubernetes, Docker и Prometheus.
Почему разработчики любят Go
Простота языка
Go прост в изучении и в понимании основных концепций. Есть популярная байка, что всю спецификацию и документацию Go можно без проблем прочитать за полдня. Разработчики, которые выбирают Go в качестве второго языка, подтверждают, что его правда освоить легче, чем другие технологии.
package main import "fmt" func main() fmt.Println("Hello, World!") >
Высокопроизводительные приложения
Go очень производителен: на нем просто писать высокопроизводительные приложения. Он был разработан для автоматизации процессов в больших масштабах, поэтому с ним можно создавать системы с высокой производительностью и нагрузкой.
Кроме того, Go отлично работает с инфраструктурой и облачными платформами. Его используют в качестве основного языка Amazon Web Services, Microsoft Azure и Google Cloud Platform (GCP).
Комьюнити и зарплаты
У Go очень живое и активное сообщество разработчиков, так как это опен-сорс проект. Они самостоятельно контрибьютят его, создают новые модули и библиотеки, а также помогают новичкам осваивать язык. Несмотря на опен-сорс историю, Go активно поддерживается Google, поэтому язык быстро развивается и активно меняется.
Про зарплаты: у Go-разработчиков вторая на IT-рынке зарплата в США, она превышает $140 тыс. в год. Однако стоит отметить, что такой перекос в зарплатах у Go-разработчиках на американском рынке может быть связан с тем, что большинство из них работают в Google, где традиционно программисты получали большую зарплату.
По результатам опроса сервиса Stack Overflow за 2021 год, Go разработчики зарабатывают за год в среднем в мире $75 тыс. в год — это делает язык восьмым по прибыльности из всех существующих. Это больше, чем Python-разработчики ($59 тыс. в год), JS-разработчики ($54 тыс. в год), Java-разработчики ($51 тыс. в год) и PHP-разработчикам ($38 тыс. в год). Вероятно, такая зарплата связана с опытом Go-разработчиков, в него редко идут джуниорами и практически не учат в качестве первого языка программирования.

На сайте HeadHunter на конец лета 2022 года было 2 641 вакансия с упоминанием языка программирования Go. Зарплаты начинаются от 80 тыс. рублей, при этом есть 40 вакансий, по которым платят более 600 тыс. рублей в месяц.
В вакансиях в связке с Go часто требуются технологии:
«Go — идеальное карьерное развитие для PHP-разработчиков»: преподаватель Хекслета Влад Гукасов — про Go-разработчиков

Преподаватель Хекслета Go Влад Гукасов рассказывает, зачем PHP-разработчики переходят на Go, почему языку практически не нужны фреймворки и какие у Go есть уникальные IT-концепции.
Меня зовут Влад Гукасов, я работаю бэкендером в международной финтех-компании Space307. Основной язык на бэкенде в нашей компании — Go.
До этого я писал на PHP, но в определенный момент появилась задача, где идеально подходил именно Go. Мы реализовывали сервис для веб-сокетов — это микросервис, поэтому PHP для этой задачи плохо подходит, зато Golang — отлично. Так я познакомился с Go, делал рабочие фичи и параллельно проходил курсы на разных платформах. Потом я поменял работу, и новую искал уже с упором на Go — теперь я поддерживаю легаси на PHP, и пишу новый код на Golang.
Вообще, Go — идеальное карьерное продолжение для PHP-разработчика. Многие программисты используют эти два языка в синергии, потому что все большие старые проекты в России написаны на PHP — «ВКонтакте», «Авито», у VK много проектов на нем. Но нагрузка постепенно растет, спектр задач расширяется, поэтому компании переходят на более эффективные и современные технологии.
Go для таких проектов идеально подходит — его легко изучить, у него огромный перформанс, он хорошо работает с железом серверов. Поэтому большинство крупных компаний пишут новые сервисы именно на нем, и нанимают бэкендеров в основном со стеком PHP/Go или Python/Go.
Плюсы Go
По синтаксису Go входит в C-подобную группу, как и многие другие языки программированию, поэтому на него легко перейти и ему легко обучиться. То есть разработчик всю жизнь писал на PHP, а потом просто взял и перешел на Go. И начал писать код в тысячи раз производительнее предыдущего. Это самый главный плюс.
Второй большой плюс: Go отлично подходит для работы с микросервисами. Go — компилируемый язык, но сам процесс компиляции занимает у него меньше секунды. То есть даже большие проекты собираются в считанные секунды — для компилированных языков это очень хорошая скорость.
Третий плюс: весь проект и вся кодовая база собирается в один бинарный файл. Это значит, что можно писать один код, который потом легко компилировать под любую платформу и архитектуру процессора — под Windows или Linux. Этим часто пользуются в DevOps, когда надо написать скрипты и скомпилировать их под каждое железо. И делается это просто одной строкой.
Go изначально был спроектирован для больших нагрузок — под ней в данном случае подразумевается количество выполняемых параллельных задач. Чтобы программа работала параллельно, нужно писать асинхронный код, который будет в один момент времени выполнять несколько действий. В Go для этого реализована концепция Green Threads в виде горутин. И так получилось, что писать асинхронный код в Go несложно, при этом он работает производительно и максимально утилизирует все ресурсы железа, в том числе ядра процессора.
Go как второй язык
Я знаю людей, которые начинали свой путь в программировании с Go — и с этим нет проблем, в нем используются те же самые концепции, что и в других языках разработки. И скорее всего, джуниор Go-разработчик сразу попадет в компанию с высокой инженерной культурой, где его будут развивать и где он сможет быстро учиться.
Чаще всего Go используют в качестве второго языка разработки. Поэтому люди, которые с ним работают, сразу видят его простоту и логичность. Например, по сравнению с Node.JS в Go весь код по умолчанию синхронен, пока ты сам не скажешь, что нужно делать по-другому. Еще в Go сложно выстрелить себе в ногу и наделать ошибок, связанных с типами данных: потому что язык не динамический, а компилируемый со статической типизацией.
Почему в Go не нужны фреймворки
Фреймворки в Go есть. Но идея языка в том, что они практически не используются, потому что готовая стандартная библиотека предоставляет все основное для разработки.
Допустим, разработчику нужно сделать обычный бэкенд веб-сервер, который будет обрабатывать какие-то самые простые запросы. На Ruby on Rails или PHP мы для этого работаем через фреймворк (в PHP сначала надо поднять Nginx — прокси, потому что PHP не может самостоятельно обрабатывать запрос).
На Go это выглядит так: программист просто пишет код, в котором использует стандартную и встроенную в язык библиотеку HTTP. Говорит — подними мне сервер на такой-то порт и обрабатывай каждый запрос так и так. Потом Go автоматически компилирует бинарник, который запускается на сервере, где обрабатывает запросы. То есть никакого дополнительного фреймворка не надо: язык сам как большой фреймворк — очень просто собрать все, что нужно.
Вообще, во фреймворках основной плюс в том, что в них автоматически все работает из коробки. В Go все нужные функции собираются отдельными пакетами: например, для работы с базой нужно выбрать, с какой именно базой будет работать программист, подключить ее и руками автоматизировать. Все процессы делаются явно, и разработчик не дистанцируется от того, что происходит внутри капота. То есть Go — очень удобный язык программирования, но какие-то его части устроены достаточно низкоуровнево.
Бесплатные курсы по программированию в Хекслете
- Освойте азы современных языков программирования
- Изучите работу с Git и командной строкой
- Выберите себе профессию или улучшите навыки
Golang: почему стоит выбрать это направление
Привет! Я — Тарас Серегин, Golang Engineering Leader в NIX.
Ежегодно на рынок выводят сотни IT-продуктов. Со временем у пользователей появляются новые запросы: изменить интерфейс, ускорить, оптимизировать приложение и так далее. Чтобы исправить баги и улучшить систему, разработчики ищут наиболее эффективное для клиента и наименее трудоемкое для себя решение.
В поиске удобных инструментов для работы в вебе инженеры Google в 2007 году задумались о более простой версии С и С++. Идею успешно реализовали в виде Golang — компилируемого многопоточного языка программирования. Планировалось, что он будет использоваться только под задачи Google (производное от Google language). Но вскоре инженеры поделились наработками со всем комьюнити.
В этой колонке я хочу рассказать о пользе применения Golang и чем направление привлекает бэкенд-разработчиков.
Популярные среди всех программистов приложения Docker и Kubernetes написаны на Go. Бэкенд мобильной версии Uber тоже. Кстати, девелоперы компании одними из первых придумали стандарт оформления и ведения кода Golang. Преуспел Go и в области блокчейна. Hyperledger Fabric — платформа для реализации блокчейн-проектов — также активно его использует. Этот список можно еще долго продолжать, но красноречивее выглядит мировая статистика.

По данным Stack Overflow, Golang входит в топ-3 языков, на котором программисты хотели бы писать код. Лидируют Python и JavaScript. В майском рейтинге PopularitY of Programming Language Golang на месте из 28. Для сравнения — еще пять лет назад он был на Все это говорит о том, что популярность и перспектива языка растет. Мой вам совет: чтобы быть на одной волне с мировым IT-сообществом — учите Golang уже сегодня.
Golang прост в изучении
Авторы Golang стремились сделать его не перегруженным. От этого язык выглядит более дружественным для новичков — порог входа в него низкий. Даже те, кто относительно недавно освоил Java, C, C++ или Python, быстро поймут и привыкнут к синтаксису Go. У него нет классов, поддержки наследования, исключений и аннотаций, что упрощает изменение кода. А с помощью утилиты GoDoc удобно документировать код.
Языку уже более десяти лет. Массивы опенсорс-кода и библиотек уже реализованы для Go, а результаты доступны на GitHub. Поэтому для многих задач можно найти готовое решение. Есть различные интеграции, а стандартная библиотека Go включает много полезных инструментов, в том числе веб-сервер и пакет тестирования, чего нет во многих языках «из коробки».
Эффективность Go — быстрый в компиляции и выполнении команд
Go компилируется гораздо быстрее, чем его аналоги С/С++. Одно из преимуществ — то, что он компилируется в бинарные файлы, и виртуальная машина не нужна (как в Java, например). Мы работаем с кроссплатформенным языком, то есть разрабатываем для любой платформы: Windows, Linux, MacOS. Просто компилируем и сразу запускаем.
Golang — один из самых быстрых и эффективных языков программирования. То, как он справляется с любой нагрузкой, не сравнимо с возможностями интерпретируемых языков вроде РНР, Node.js, Ruby и другими.
В Java или С# вы могли встретить такой термин, как многопоточность. Этот механизм призван задействовать все ресурсы компьютера, на котором запускается программа, чтобы решать трудоемкие задачи максимально эффективно и быстро. Например, перелопачивание больших объемов данных в нескольких потоках или рассылка огромного количества писем. Достигается это с помощью встроенных примитивов — горутин (threads). Создать такую процедуру в Go просто: добавляем ключевое слово go перед функцией.
Горутины очень легковесны. Если сравнивать с потоками Java, который потребляет много оперативной памяти, Go требуются буквально мегабайты. Он является достаточно щадящим для ресурсов системы. Среда выполнения Golang позволяет одновременно запускать тысячи горутин. При этом обслуживание инфраструктуры обойдется недорого. Переплачивать за хостинг не придется.
Легок в интеграции с текущим бэкендом
Полностью переписывать на Go действующий проект, на которым вы работаете, бизнесу может быть дорого и долго. Есть решение — интегрировать в текущий проект Go-бэкенд. Например, есть большое приложение на РНР. Мы можем дополнить его новыми сервисами на Go, и они будут отлично уживаться вместе. То же самое касается интеграции с Java, Python и другими бэкенд языками. Еще один плюс — на Go есть множество библиотек для интеграции: PostgreSQL, MySQL, RabbitMQ, Redis, GraphQL и другие.
Удобен для реализации микросервисной архитектуры
Сегодня в больших проектах очень популярен подход микросервисной архитектуры. Почему? Современные приложения содержат большое количество внешних сервисов: базы данных, кеши, поисковые движки, очереди сообщений и так далее. Разработчики смотрят в будущее и разбирают сложные проекты на более мелкие, закрывающие конкретные запросы бизнеса. Одни конечные продукты клиент может предоставлять определенным пользователям, другие — перепродавать сторонним компаниям. Go отлично подходит для последующих разработок. В нем используется асинхронный ввод/вывод, поэтому приложение может взаимодействовать с любым количеством сервисов, не блокируя веб-запросы. Протоколы gRPC позволяют микросервисам беспрепятственно общаться между собой.
Широкие возможности применения
Язык обладает встроенными возможностями (concurrency) многопоточности для обработки больших объемов данных. Например, для email-рассылок и нотификаций. Все, что касается в этом плане web-сервисов, легко реализовать на Go:
- системы потокового видео/аудио (чаты, стриминговые сервисы);
- высоконагруженные API;
- парсеры с большими объемами данных (XML, JSON, CSV);
- system apps (системные кроссплатформенные приложения, которые можно запускать на разных операционных системах);
- serverless web services (AWS Lambda, Google cloud functions for Firebase);
- notification services.
А где Golang лучше не применять? В открытых источниках вы можете найти библиотеки для реализации GUI-интерфейса на Go. Но, на мой взгляд, Desktop GUI приложения лучше на нем не писать. Все-таки язык создавался для решения задач в вебе. Такие же сомнительные «поделки» попадаются на GitHub в сферах геймдева и мобильной разработки.
Опыт нашей команды
Мы в NIX пишем на Golang с 2019 года. На данный момент в команде порядка 20 человек с экспертизой в этом языке. За два года мы успешно реализовали около десяти проектов на Go. Среди них — разработки в таких доменах, как fintech, real estate, высоконагруженный сервис по обработке видео, спортивные новости и другие.
Почему выбрали Go? Например, в проекте с онлайн-банкингом мы имели дело с сотнями тысяч пользовательских транзакций. В приложении для обработки видео — с сервисом, который должен был запускаться на Windows, так как был задействован вспомогательный софт и «железо» под эту платформу. В сервисе спортивных новостей — тысячи онлайн-юзеров, real time данные и высокие требования по скорости доставки контента на фронтенд. Во всех случаях нам пригодились ключевые возможности языка — concurrency и кроссплатформенность. Словом, везде, где мы использовали Go по назначению, имеем только положительный опыт.
Как и в любом бизнесе, в IT время на разработку — это деньги. Заказчики не хотят терять ни того ни другого. Поэтому команде важно оперативно решать технические таски. Современному бэкенд-разработчику нужно владеть как минимум одним языком, на котором быстро решаются бизнес-задачи. Golang отлично для этого подходит. При необходимости некоторые участки приложения вы сможете выносить в микросервисы на Go. При грамотном проектировании сочетание Golang с другими бэкенд-языками дает потрясающие результаты — конкурентный продукт и довольного клиента.
Подобається Сподобалось 6
До обраного В обраному 5
Язык Go для начинающих

Цель этой статьи — рассказать о языке программирования Go (Golang) тем разработчикам, которые смотрят в сторону этого языка, но еще не решились взяться за его изучение. Рассказ будет вестись на примере реального приложения, которое представляет из себя RESTful API веб-сервис.
Передо мной стояла задача разработать бэкэнд к мобильному сервису. Суть сервиса довольно проста. Мобильное приложение, которое показывает посты пользователей, находящихся рядом с текущим местоположением. На посты пользователи могут оставлять свои комментарии, которые тоже, в свою очередь, можно комментировать. Получается своеобразный гео-форум.
Давно хотел попробовать применить язык Go для сколь нибудь серьезных проектов. Выбор был очевиден, благо что этот язык как нельзя лучше подходит для подобных задач.
Основные преимущества языка Go:
- Простой и понятный синтаксис. Это делает написание кода приятным занятием.
- Статическая типизация. Позволяет избежать ошибок, допущенных по невнимательности, упрощает чтение и понимание кода, делает код однозначным.
- Скорость и компиляция. Скорость у Go в десятки раз быстрее, чем у скриптовых языков, при меньшем потреблении памяти. При этом, компиляция практически мгновенна. Весь проект компилируется в один бинарный файл, без зависимостей. Как говорится, «просто добавь воды». И вам не надо заботиться о памяти, есть сборщик мусора.
- Отход от ООП. В языке нет классов, но есть структуры данных с методами. Наследование заменяется механизмом встраивания. Существуют интерфейсы, которые не нужно явно имплементировать, а лишь достаточно реализовать методы интерфейса.
- Параллелизм. Параллельные вычисления в языке делаются просто, изящно и без головной боли. Горутины (что-то типа потоков) легковесны, потребляют мало памяти.
- Богатая стандартная библиотека. В языке есть все необходимое для веб-разработки и не только. Количество сторонних библиотек постоянно растет. Кроме того, есть возможность использовать библиотеки C и C++.
- Возможность писать в функциональном стиле. В языке есть замыкания (closures) и анонимные функции. Функции являются объектами первого порядка, их можно передавать в качестве аргументов и использовать в качестве типов данных.
- Авторитетные отцы-основатели и сильное комьюнити. Роб Пайк, Кен Томпсон, Роберт Гризмер стояли у истоков. Сейчас у языка более 300 контрибьюторов. Язык имеет сильное сообщество и постоянно развивается.
- Open Source
- Обаятельный талисман
Все эти, и многие другие особенности позволяют выделить язык среди остальных. Это достойный кандидат на изучение, к тому же, освоить язык довольно просто.
Итак, вернемся к нашей задаче. Хоть язык и не накладывает ограничений на структуру проекта, данное приложение я решил организовать по модели MVC. Правда View реализовывается на стороне клиента. В моем случае это был AngularJS, в перспективе — нативное мобильное приложение. Здесь я расскажу лишь об API на стороне сервиса.
Структура проекта получилась следующая:
/project/ /conf/ errors.go settings.go /controllers/ posts.go users.go /models/ posts.go users.go /utils/ helpers.go loctalk.go
Программа в Go разделяется на пакеты (package), что указывается в начале каждого файла. Имя пакета должно соответствовать директории в которой находятся файлы, входящие в пакет. Так же, должен быть главный пакет main с функцией main(). Он у меня находится в корневом файле приложения loctalk.go. Таким образом, у меня получилось 5 пакетов: conf, controllers, models, utils, main.
Буду приводить неполное содержание файлов, а только минимально необходимое для понимания.
Пакет conf содержит константы и настройки сайта.
package conf import ( "os" ) const ( SITE_NAME string = "LocTalk" DEFAULT_LIMIT int = 10 MAX_LIMIT int = 1000 MAX_POST_CHARS int = 1000 ) func init() < mode := os.Getenv("MARTINI_ENV") switch mode < case "production": SiteUrl = "http://loctalk.net" AbsolutePath = "/path/to/project/" default: SiteUrl = "http://127.0.0.1" AbsolutePath = "/path/to/project/" >>
Думаю, комментировать тут нечего. Функция init() вызывается в каждом пакете до вызова main(). Их может быть несколько в разных файлах.
package main import ( "github.com/go-martini/martini" "net/http" "loctalk/conf" "loctalk/controllers" "loctalk/models" "loctalk/utils" ) func main() < m := martini.Classic() m.Use(func(w http.ResponseWriter) < w.Header().Set("Content-Type", "application/json; charset=utf-8") >) m.Map(new(utils.MarshUnmarsh)) Auth := func(mu *utils.MarshUnmarsh, req *http.Request, rw http.ResponseWriter) < reqUserId := req.Header.Get("X-Auth-User") reqToken := req.Header.Get("X-Auth-Token") if !models.CheckToken(reqUserId, reqToken) < rw.WriteHeader(http.StatusUnauthorized) rw.Write(mu.Marshal(conf.ErrUserAccessDenied)) >> // ROUTES m.Get("/", controllers.Home) // users m.Get("/api/v1/users", controllers.GetUsers) m.Get("/api/v1/users/:id", controllers.GetUserById) m.Post("/api/v1/users", controllers.CreateUser) // … // posts m.Get("/api/v1/posts", controllers.GetRootPosts) m.Get("/api/v1/posts/:id", controllers.GetPostById) m.Post("/api/v1/posts", Auth, controllers.CreatePost) // . m.Run() >
В самом верху определяется имя пакета. Далее идет список импортируемых пакетов. Мы будем использовать пакет Martini. Он добавляет легкую прослойку для быстрого и удобного создания веб-приложений. Обратите внимание как импортируется этот пакет. Нужно указать путь к репозиторию откуда он был взят. А чтобы его получить, достаточно в консоли набрать команду go get github.com/go-martini/martini
Далее мы создаем экземпляр Martini, настраиваем и запускаем его. Обратите внимание на знак « := ». Это сокращенный синтаксис, он означает: создать переменную соответствующего типа и инициализировать ее. Например, написав a := «hello», мы создадим переменную a типа string и присвоим ей строку «hello».
Переменная m в нашем случае имеет тип *ClassicMartini, именно это возвращает martini.Classic(). * означает указатель, т. е. передается не само значение, а лишь указатель на него. В метод m.Use() мы передаем функцию-обработчик. Этот Middleware позволяет Martini делать определенные действия над каждым запросом. В данном случае, мы определяем Content-Type для каждого запроса. Метод m.Map() же позволяет привязать нашу структуру и использовать ее затем в контроллерах при необходимости (механизм dependency injection). В данном случае, я создал обертку для кодирования структуры данных в формат json.
Тут же мы создаем внутреннюю функцию Auth, которая проверяет авторизацию пользователя. Ее можно вставить в наши роуты и она будет вызываться до вызова контроллера. Эти вещи возможны благодаря Martini. С использованием стандартной библиотеки код получился бы немного другой.
Взглянем на файл errors.go пакета conf.
package conf import ( "fmt" "net/http" ) type ApiError struct < Code int `json:"errorCode"` HttpCode int `json:"-"` Message string `json:"errorMsg"` Info string `json:"errorInfo"` >func (e *ApiError) Error() string < return e.Message >func NewApiError(err error) *ApiError < return &ApiError> var ErrUserPassEmpty = &ApiError var ErrUserNotFound = &ApiError var ErrUserIdEmpty = &ApiError var ErrUserIdWrong = &ApiError // … и т. д.
Язык поддерживает возврат нескольких значений. Вместо механизма try-catch, очень часто используется прием, когда вторым аргументом возвращается ошибка. И при ее наличии, она обрабатывается. Есть встроенный тип error, который представляет из себя интерфейс:
type error interface
Таким образом, чтобы реализовать этот интерфейс, достаточно иметь метод Error() string. Я создал свой тип для ошибок ApiError, который более специфичен для моих задач, однако совместим со встроенным типом error.
Обратите внимание на — type ApiError struct. Это определение структуры, модели данных, которую вы будете использовать постоянно в своей работе. Она состоит из полей определенных типов (надеюсь, вы успели заметить, что тип данных пишется после имени переменной). Кстати, полями могут быть другие структуры, наследуя все методы и поля. В одинарных кавычках « указаны теги. Их указывать не обязательно. В данном случае они используются пакетом encoding/json для указания имени в выводе json (знак минус «-» вообще исключает поле из вывода).
Обратите внимание, что поля структуры написаны с заглавной буквы. Это означает, что они имеют область видимости за пределами пакета. Если написать их с прописной буквы, они экспортироваться не будут, а будут доступны только в пределах пакета. Это же относится и к функциям и методам. Вот такой простой механизм инкапсуляции.
Двигаемся дальше. Определение func (e *ApiError) Error() string означает ни что иное, как метод данной структуры. Переменная e — это указатель на структуру, своего рода self/this. Соответственно вызвав метод .Error() на структуре, мы получим ее поле Message.
Далее мы определяем предустановленные ошибки и заполняем их поля. Поля вида http.StatusBadRequest — это значения типа int в пакете http для стандартных кодов ответа, своего рода алиасы. Мы используем сокращенный синтаксис объявления структуры &ApiError<> с инициализацией. По другому можно было бы написать так:
MyError := new(ApiError) MyError.Code = 110 // …
Символ & означает получить указатель на данную структуру. Оператор new() так же возвращает указатель, а не значение. По-началу возникает небольшая путаница с указателями, но, со временем, вы привыкните.
Перейдем к нашим моделям. Приведу урезанную версию модели постов:
package models import ( "labix.org/v2/mgo/bson" "loctalk/conf" "loctalk/utils" "time" "unicode/utf8" "log" ) // GeoJSON format type Geo struct < Type string `json:"-"` Coordinates [2]float64 `json:"coordinates"` >type Post struct < Id bson.ObjectId `json:"id" bson:"_id,omitempty"` UserId bson.ObjectId `json:"userId"` UserName string `json:"userName"` ThumbUrl string `json:"thumbUrl"` ParentId bson.ObjectId `json:"parentId,omitempty" bson:",omitempty"` Enabled bool `json:"-"` Body string `json:"body"` Geo Geo `json:"geo"` Date time.Time `json:"date" bson:",omitempty"` >func NewPost() *Post < return new(Post) >func (p *Post) LoadById(id string) *conf.ApiError < if !bson.IsObjectIdHex(id) < return conf.ErrPostIdWrong >session := utils.NewDbSession() defer session.Close() c := session.Col("posts") err := c.Find(bson.M).One(p) if p.Id == "" < return conf.ErrPostNotFound >if err != nil < return conf.NewApiError(err) >return nil > func (p *Post) Create() (id string, err *conf.ApiError) < // validation switch < case p.UserId == "": err = conf.ErrUserIdEmpty case p.Body == "": err = conf.ErrPostBodyEmpty case utf8.RuneCountInString(p.Body) >conf.MAX_POST_CHARS: err = conf.ErrPostMaxSize case p.Geo.Coordinates[0] == 0.0 || p.Geo.Coordinates[1] == 0.0: err = conf.ErrPostLocationEmpty > if err != nil < return >p.Id = bson.NewObjectId() p.Geo.Type = "Point" p.Enabled = true p.Date = time.Now() session := utils.NewDbSession() defer session.Close() c := session.Col("posts") errDb := c.Insert(p) if errDb != nil < return "", conf.NewApiError(errDb) >return p.Id.Hex(), nil > func (p *Post) Update() *conf.ApiError < session := utils.NewDbSession() defer session.Close() c := session.Col("posts") err := c.UpdateId(p.Id, p) if err != nil < return conf.NewApiError(err) >return nil > func (p *Post) Disable() *conf.ApiError < session := utils.NewDbSession() defer session.Close() p.Enabled = false c := session.Col("posts") err := c.UpdateId(p.Id, p) if err != nil < return conf.NewApiError(err) >return nil > // …
Здесь мы используем замечательный драйвер для MongoDb — mgo, чтобы сохранять данные. Для удобства, я создал небольшую обертку над api mgo — utils.NewDbSession. Логика работы с данными: сначала мы создаем объект во внутренней структуре языка, а затем, с помощью метода этой структуры, сохраняем его в базу данных.
Обратите внимание, что в этих методах мы везде используем наш тип ошибки conf.ApiError. Стандартные ошибки мы конвертируем в наши с помощью conf.NewApiError(err). Так же, важен оператор defer. Он исполняется в самом конце выполнения метода. В данном случае, закрывает соединение с БД.
Что ж, осталось взглянуть на контроллер, который обрабатывает запросы и выводит json в ответ.
package controllers import ( "encoding/json" "fmt" "github.com/go-martini/martini" "labix.org/v2/mgo/bson" "loctalk/conf" "loctalk/models" "loctalk/utils" "net/http" ) func GetPostById(mu *utils.MarshUnmarsh, params martini.Params) (int, []byte) < id := params["id"] post := models.NewPost() err := post.LoadById(id) if err != nil < return err.HttpCode, mu.Marshal(err) >return http.StatusOK, mu.Marshal(post) > // .
Здесь мы получаем из URL id запрашиваемого поста, создаем новый экземпляр нашей структуры и вызываем на ней метод LoadById(id) для загрузки данных из БД и заполнения данной структуры. Которую мы и выводим в HTTP ответ, предварительно преобразовав в json нашим методом mu.Marshal(post).
Обратите внимание на сигнатуру функции:
func GetPostById(mu *utils.MarshUnmarsh, params martini.Params) (int, []byte)
Входные параметры нам предоставляет Martini с помощью механизма внедрения зависимостей (dependency injection). И мы возвращаем два параметра (int, []byte) — число (статус ответа) и массив байт.
Итак, мы разобрали основные компоненты и подходы, используя которые, вы сможете сделать эффективный RESTful API интерфейс в короткие сроки. Надеюсь, статья была полезна и вдохновит некоторых из вас заняться изучением замечательного языка Go. Уверен, за ним будущее.
Для изучения могу порекомендовать хорошую книгу на русском «Программирование на языке Go» Марка Саммерфильда. И, конечно, больше практиковаться.
UPD: Tour Go на русском.