Erhalten Sie Zugang zu diesem und mehr als 300000 Büchern ab EUR 5,99 monatlich.
Go быстро завоевал популярность у разработчиков веб-сервисов. Существует множество учебников, помогающих программистам со знанием других языков освоить его синтаксис, но этого недостаточно. Автор Джон Боднер познакомит вас с паттернами проектирования, созданными опытными инженерами Go, и обоснует их применение. В книге собрана наиболее важная информация, необходимая для написания чистого и идиоматического кода. Начните думать как Go-разработчик, вне зависимости от уровня подготовки. В обновленном издании также рассказывается и о современных инструментах Go, упрощающих решение задач, трудновыполнимых на других платформах.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 645
Veröffentlichungsjahr: 2025
Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:
Переводчики Л. Киселева, С. Черников
Джон Боднер
Go: идиомы и паттерны проектирования, 2-е изд.. — Астана: "Спринт Бук", 2025.
ISBN 978-601-08-4721-7
© ТОО "Спринт Бук", 2025
Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.
Первое издание книги «Go: идиомы и паттерны проектирования» было отличной отправной точкой для любого разработчика, заинтересованного в изучении Go, а второе издание стало еще более совершенным. В этой книге нет монотонности, и она идеально подходит для того, чтобы новички познакомились с экосистемой Go.
Джонатан Холл (Jonathan Hall), разработчик Go и создатель контента
Книга «Go: идиомы и паттерны проектирования» не просто обучает языку программирования Go, она учит хорошему идиоматическому Go. Это идеальная книга для программистов, которые хотят освоить Go.
Крис Хайнс (Chris Hines), ведущий инженер-программист, Comcast
Go — уникальный язык, и даже опытным программистам приходится забыть о том, как делаются некоторые вещи, и научиться иному подходу к программному обеспечению. Автор хорошо объясняет основные возможности языка, сопровождая теорию примерами идиоматического кода и описанием возможных подводных камней.
Аарон Шлезингер (Aaron Schlesinger), ведущий разработчик, Microsoft
Джон на протяжении многих лет пользуется большим авторитетом в Go-сообществе: его высказывания и статьи часто несут в себе много полезного. Эта книга представляет собой руководство по изучению языка Go, рассчитанное на программистов. Она отлично сбалансирована в том плане, что хорошо объясняет необходимые вещи, не пересказывая общеизвестные концепции.
Стив Франсиа (Steve Francia), создатель Hugo, Cobra и Viper, ведущий менеджер по Go-продуктам, Google
Боднер предлагает нам настоящий Go. В ясной, живой манере он учит этому языку от самых его основ до таких продвинутых тем, как рефлексия и взаимодействие с кодом, написанным на языке C. Многочисленные примеры показывают, как следует писать идиоматический Go-код, уделяя особое внимание ясности и простоте. Также подробно объясняется, как те или иные базовые концепции влияют на поведение программ, например как указатели влияют на распределение памяти и сборку мусора. Эта книга поможет новичкам очень быстро выйти на должный уровень, и даже опытные Go-программисты найдут в ней что-то полезное.
Джонатан Амстердам (Jonathan Amsterdam), сотрудник подразделения Go-разработки, Google
Книга «Go: идиомы и паттерны проектирования» содержит важную вводную информацию о том, что именно делает уникальным язык программирования Go, а также о паттернах проектирования и идиомах, придающих ему чрезвычайную мощь. Джону Боднеру удалось показать связь между базовыми возможностями Go и его философией, ориентируя читателей писать Go-код так, как это было задумано создателями языка.
Роберт Лебовиц (Robert Liebowitz), разработчик, Morning Consult
Джон написал не просто руководство по Go — издание дает идиоматически и практически ориентированное понимание этого языка. Книга базируется на богатом опыте Джона в IT-отрасли, она поможет тем, кто хочет очень быстро научиться эффективно пользоваться этим языком.
Уильям Кеннеди (William Kennedy), управляющий партнер, Ardan Labs
В предисловии к первому изданию я написал:
«Изначально я хотел назвать эту книгу “Скучный Go”, потому что Go — это и правда очень скучно…
Однако если Go скучен, это еще не значит, что он примитивен. Для правильного использования этого языка необходимо четко понимать, как его функции сочетаются друг с другом. Хотя вы вполне можете написать на Go такой код, который будет выглядеть почти так же, как код на Java или Python, но результат вас не слишком обрадует и вы так и не поймете, к чему была вся эта суета. Вот тут-то и пригодится эта книга. Она познакомит вас с возможностями Go и объяснит, как лучше их использовать для написания расширяемого идиоматического кода».
Язык Go остался маленьким языком с небольшим набором возможностей. В нем по-прежнему отсутствует наследование, аспектно-ориентированное программирование, перегрузка функций, перегрузка операторов, сопоставление шаблонов, нет именованных параметров, исключений и многих других возможностей, которые удовлетворяют требованиям других языков. Так почему же нужно было обновлять эту книгу о скучном языке?
Это издание появилось по нескольким причинам. Во-первых, скучное не значит банальное, но это не значит и неизменное. За последние три года появились новые функции, инструменты и библиотеки. Такие улучшения, как структурированное ведение журнала, нечеткое тестирование — фаззинг, рабочие среды и проверка уязвимостей, помогают разработчикам Go создавать надежный, долговечный и поддерживаемый код. Теперь, когда за их плечами есть опыт нескольких лет работы с универсальными шаблонами, стандартная библиотека стала включать в себя ограничения типов и родовые функции для сокращения повторяющегося кода. Был даже обновлен незащищенный (unsafe) пакет — он стал немного безопаснее. И разработчикам Go нужен ресурс, объясняющий, как наилучшим образом использовать новые возможности.
Во-вторых, в первом издании некоторые аспекты Go были раскрыты не совсем верно. Вводная глава была написана не так хорошо, как хотелось бы. Богатая экосистема инструментов Go не была изучена. А читатели первого издания просили добавить упражнения и дополнительные примеры кода. В этом издании я попытался устранить названные недостатки.
В-третьих, команда разработчиков Go представила нечто новое и, осмелюсь сказать, захватывающее. Теперь существует стратегия, которая позволяет Go поддерживать обратную совместимость, необходимую для долгосрочных проектов по разработке программного обеспечения, и в то же время дает возможность вносить кардинальные изменения, позволяющие устранить давние недостатки дизайна. Новые правила определения области переменных цикла for, введенные в версии Go 1.22, — это первая функция, использующая преимущества этого подхода.
Язык Go по-прежнему можно назвать скучным, но он все так же прекрасен и сегодня стал лучше, чем когда-либо. Надеюсь, второе издание вам понравится.
Целевая аудитория — разработчики, желающие изучить второй (или любой по счету) язык программирования. Она подойдет как новичкам, которые знают лишь то, что у Go есть забавный талисман, так и тем, кто уже успел прочитать краткое руководство по этому языку или даже написать на нем несколько фрагментов кода. Эта книга не просто рассказывает, как следует писать программы на Go, она показывает, как можно делать это идиоматически. Более опытные Go-разработчики найдут здесь советы по применению новых возможностей языка.
Предполагается, что читатель уже умеет пользоваться таким инструментом разработчика, как система контроля версий (желательно Git) и IDE. Читатель должен быть знаком с такими базовыми понятиями информатики, как конкурентность и абстракция, поскольку в книге мы будем касаться этих тем применительно к Go. Одни примеры кода можно скачать с GitHub, а десятки других — запустить в онлайн-песочнице The Go Playground. Наличие соединения с Интернетом необязательно, однако с ним будет проще изучать исполняемые примеры кода. Поскольку Go часто используется для создания и вызова HTTP-серверов, для понимания некоторых примеров читатель должен иметь общее представление о протоколе HTTP и связанных с ним концепциях.
Несмотря на то что большинство функций Go встречаются и в других языках, программы, написанные на этом языке, имеют иную структуру. В книге мы начнем с настройки среды разработки для языка Go, после чего поговорим о переменных, типах, управляющих конструкциях и функциях. Если вам захочется пропустить этот материал, постарайтесь удержаться от этого и все-таки ознакомиться с ним. Зачастую именно такие детали делают Go-код идиоматическим. Простые на первый взгляд вещи могут оказаться очень интересными, если вы присмотритесь к ним получше.
В этой книге применяются следующие шрифтовые выделения.
Курсивный шрифт
Используется для выделения новых терминов.
Шрифт с засечками
Применяется для выделения URL-адресов, адресов электронной почты и элементов интерфейса.
Моноширинный шрифт
Используется для записи листингов программ, а также для выделения в тексте таких элементов, как имена переменных и функций, базы данных, типы данных, переменные среды, операторы и ключевые слова, имена и расширения файлов.
Полужирный моноширинный шрифт
Применяется для выделения команд и другого текста, который должен вводиться пользователем без каких-либо изменений.
Курсивный моноширинный шрифт
Применяется для обозначения в коде элементов, вместо которых следует подставить предоставленные пользователем значения или значения, зависящие от контекста.
Так обозначается совет или предложение.
Так обозначается примечание общего характера.
Так обозначается предупреждение.
Вспомогательные материалы (примеры программного кода, упражнения и т.д.) доступны для скачивания по адресу https://github.com/learning-go-book-2e.
В общем случае все примеры кода из книги вы можете использовать в своих программах и в документации. Вам не нужно обращаться в издательство за разрешением, если вы не собираетесь воспроизводить существенные части программного кода. Если вы разрабатываете программу и используете в ней несколько фрагментов кода из книги, вам не нужно обращаться за разрешением. Но для продажи или распространения примеров из книги вам потребуется разрешение от издательства O’Reilly. Вы можете отвечать на вопросы, цитируя данную книгу или примеры из нее, но для включения существенных объемов программного кода из книги в документацию вашего продукта потребуется разрешение.
Мы рекомендуем, но не требуем добавлять ссылку на первоисточник при цитировании. Под ссылкой на первоисточник мы подразумеваем указание авторов, издательства и ISBN.
За получением разрешения на использование значительных объемов программного кода из книги обращайтесь по адресу [email protected].
Я был невероятно польщен реакцией на первое издание этой книги. Работа над ней началась в конце 2019 года, завершилась в конце 2020-го, книга вышла в начале 2021 года. Невольно она стала моим собственным пандемическим проектом. Кто-то пек хлеб, а я объяснял, как пользоваться указателями.
После завершения работы над книгой меня стали спрашивать, какой будет следующая. Я ответил, что собираюсь взять заслуженный перерыв, а затем приступить к работе над любовным романом. Но не успел я начать писать о пиратах и принцессах, как случилось нечто удивительное: книга стала пользоваться огромным успехом. Большую часть года она входила в пятерку самых популярных обучающих книг на сайте издательства O’Reilly. По мере того как продавалось первое издание, я замечал в нем разные места, которые хотелось бы исправить, а также стал получать от читателей письма, где они указывали на ошибки и упущения. Некоторые из них были исправлены в допечатках, но я связался с издательством, чтобы узнать, не хотят ли они выпустить новое издание, и они заинтересовались моим предложением.
Мне было приятно вернуться к сотрудничеству с O’Reilly и приступить к работе над вторым изданием. Рита Фернандо (Rita Fernando) помогала нам в работе, направляла, давала обратную связь и редактировала книгу. Это издание стало неизмеримо лучше благодаря отзывам Джонатана Амстердама (Jonathan Amsterdam), Лима Холла (Leam Hall), Кэти Хокман (Katie Hockman), Томаса Хантера (Thomas Hunter), Макса Хорстманна (Max Horstmann) и Натали Пистунович (Natalie Pistunovich). Крис Хайнс (Chris Hines) проделал невероятно тщательную работу, выявив мои ошибки и предложив лучшие примеры. Комментарии и отзывы Эбби Денг (Abby Deng) и членов книжного клуба Go в Datadog позволили мне внести изменения с учетом отзывов разработчиков, только начавших освоение Go. Оставшиеся (надеюсь, немногочисленные) ошибки принадлежат мне.
Моя жена и дети отнеслись с пониманием и не возражали против того, чтобы я пропускал вечерние семейные просмотры фильмов и проводил это время, придумывая, как лучше описать новые возможности Go.
Я также хочу поблагодарить читателей первого издания, которые написали мне столько добрых слов. Благодарю всех вас за вашу поддержку и вдохновение.
Хоть и считается, что писательство — это индивидуальное занятие, книга не может появиться на свет без помощи множества других людей. Однажды я сказал Кармен Андо (Carmen Andoh), что собираюсь написать книгу по языку Go, и на конференции GopherCon 2019 она познакомила меня с Зан Маккуэйд (Zan McQuade) из компании O’Reilly. Зан помогла мне заключить договор с издательством, после чего регулярно консультировала меня по мере прогресса в написании книги. Мишель Кронин (Michele Cronin) редактировала мои тексты, высказывала замечания и выслушивала меня, когда я неизбежно сталкивался с трудностями. Технический редактор Тоня Трибула (Tonya Trybula) и литературный редактор Бет Келли (Beth Kelly) довели мою рукопись до пригодного для печати вида.
По мере написания книги я получал важные замечания и слова поддержки от многих людей, в числе которых были Джонатан Альтман (Jonathan Altman), Джонатан Амстердам (Jonathan Amsterdam), Джонни Рэй Остин (Johnny Ray Austin), Крис Фойербах (Chris Fauerbach), Крис Хайнс (Chris Hines), Билл Кеннеди (Bill Kennedy), Тони Нельсон (Tony Nelson), Фил Перл (Phil Pearl), Лиз Райс (Liz Rice), Аарон Шлезингер (Aaron Schlesinger), Крис Стаут (Chris Stout), Капил Тхангавелу (Kapil Thangavelu), Клэр Тривисонно (Claire Trivisonno), Фолькер Уриг (Volker Uhrig), Джефф Уэндлинг (Jeff Wendling) и Крис Сарагоса (Kris Zaragoza). Особых слов признательности заслуживает Роб Лебовиц (Rob Liebowitz), подробные замечания и быстрые ответы которого сделали эту книгу гораздо лучше.
Моей семье приходилось мириться с тем, что вечера и выходные дни я работал за компьютером, вместо того чтобы проводить это время с ними. Моя жена Лора великодушно делала вид, что я не разбудил ее, когда я добирался до кровати в час ночи или еще позже.
Наконец, хочется вспомнить о тех людях, которые направили меня по этому пути четыре десятилетия назад. Первым из них был отец моего друга детства Пол Голдштейн (Paul Goldstein). В 1982 году он показал нам компьютер Commodore PET, ввел команду PRINT2+2 и нажал клавишу ввода. Я был поражен, когда на экране появилась цифра 4, и заболел этим раз и навсегда. Спустя какое-то время Пол научил меня программировать и даже на несколько недель одолжил свой компьютер. А вторым человеком является моя мама, которую я должен поблагодарить за то, что она поощряла мой интерес к программированию и компьютерам, даже толком не понимая, что это такое. В свое время она купила мне картридж для игровой приставки Atari 2600, позволявший писать программы на языке BASIC, компьютеры Commodore VIC-20 и Commodore 64, а также книги по программированию, после прочтения которых у меня появилась мечта когда-нибудь написать собственную книгу.
Спасибо всем вам за то, что помогли мне сделать эту мечту реальностью!
Ваши замечания, предложения, вопросы отправляйте по адресу
(издательство «SprintBook», компьютерная редакция).
Мы будем рады узнать ваше мнение!
Мы выражаем огромную благодарность клубу рецензентов ИТ-литературы ReadIT Club за помощь в работе над русскоязычным изданием книги и их вклад в повышение качества переводной литературы.
Мы будем рады узнать ваше мнение!
Дмитрий Бардин — ведущий разработчик, архитектор решений, один из авторов курса «Архитектор ПО» от «Яндекс Практикума». В настоящее время занимается разработкой бэкенда «КиноПоиска» с применением как языка Go, так и языка Java. В прошлом руководитель службы продуктовой разработки и ресурс-менеджер. Опыт в ИТ — более 15 лет.
Любой язык программирования нуждается в среде разработки, и Go не исключение. Если вы уже успели создать на Go одну-две программы, то у вас уже, вероятно, имеется рабочая среда, но при этом вы могли упустить из виду некоторые новые методы и инструменты. Если же вы в первый раз настраиваете свой компьютер для разработки на Go, не беспокойтесь: установка этого языка и его вспомогательных инструментов не составляет большого труда. После того как вы настроите среду и убедитесь, что все сделано правильно, мы напишем простую программу и опробуем несколько способов компиляции и запуска Go-кода, после чего рассмотрим несколько инструментов и методов, упрощающих процесс разработки на Go.
Чтобы приступить к написанию кода на Go, нужно установить средства разработки. Последнюю версию этих инструментов можно скачать с официального сайта языка Go (https://golang.org/dl). Скачайте и установите версию, подходящую для вашей платформы. Установочные пакеты с расширением .pkg для Mac и расширением .msi для Windows автоматически установят Go в нужном каталоге, удалят ранее установленные файлы и разместят исполняемый файл языка Go в соответствии с путем по умолчанию для исполняемых файлов.
Для платформы Mac средства разработки для языка Go можно установить с помощью менеджера пакетов Homebrew (https://brew.sh), выполнив команду brewinstallgo. Для Windows это можно сделать с помощью менеджера пакетов Chocolatey (https://chocolatey.org), выполнив команду chocoinstallgolang.
Версии установочных пакетов для Linux и BSD представляют собой сжатые TAR-файлы, которые распаковываются в каталог с именем go. Скопируйте этот каталог в /usr/local и добавьте путь /usr/local/go/bin в переменную среды $PATH, чтобы сделать доступной команду go:
$ tar -C /usr/local -xzf go1.20.5.linux-amd64.tar.gz
$ echo 'export PATH=$PATH:/usr/local/go/bin' >> $HOME/.bash_profile
$ source $HOME/.bash_profile
Для записи в /usr/local могут потребоваться полномочия root. Если команда tar не выполняется, выполните ее повторно с помощью sudotar-C/usr/local-xzfgo1.20.5.linux-amd64.tar.gz.
Go-программы компилируются в один нативный двоичный файл и не требуют установки дополнительного программного обеспечения для запуска. Устанавливать средства разработки для языка Go нужно только на тех компьютерах, на которых вы будете компилировать Go-программы. В этом состоит отличие от таких языков, как Java, Python и JavaScript, которые требуют установки виртуальной машины для запуска программы. Использование одного собственного двоичного файла значительно упрощает распространение программ, написанных на языке Go. В этой книге не рассматриваются контейнеры, но разработчики, применяющие Docker или Kubernetes, часто могут упаковать приложение Go в образ scratch или distroless. Подробнее об том можете почитать в блоге Герта Бека (Geert Baeke), в статье Distroless or scratch for Go apps? (https://oreil.ly/W0VUB).
Чтобы убедиться, что ваша среда правильно настроена, откройте окно терминала или командной строки и введите команду:
$ go version
Если все в порядке, то вы увидите что-то наподобие следующего:
go version go1.20.5 darwin/amd64
Это сообщение говорит о наличии компилятора Go версии 1.20.5 для macOS. (Darwin — это операционная система, лежащая в основе macOS, а arm64 — название 64-разрядных чипов, основанных на разработках ARM.) В x64 Linux вы увидите:
go version go1.20.5 linux/amd64
Если вместо сообщения с описанием версии вы увидите сообщение об ошибке, значит, у вас нет файла go в каталоге, заданном в качестве пути для исполняемых файлов, или в этом файле находится другая программа с таким же именем. В macOS или других Unix-подобных системах можно выяснить, какой файл go запускается и запускается ли вообще, с помощью команды whichgo. Если ничего не возвращается, скорректируйте у себя путь для исполняемых файлов.
Если работаете в Linux или BSD, ошибка может состоять в том, что вы установили 64-разрядную версию средств разработки для языка Go в 32-разрядной системе или версию для другой процессорной архитектуры.
Доступ ко всем инструментам разработки на Go осуществляется с помощью команды go. Помимо goversion, есть компилятор gobuild, средство форматирования кода gofmt, менеджер зависимостей gomod, средство запуска тестов gotest, инструмент для поиска распространенных ошибок при кодировании govet и многое другое. Подробно о них рассказывается в главах 10, 11 и 15. А пока давайте вкратце рассмотрим наиболее часто используемые инструменты на примере создания всеми любимого первого приложения «Hello, World!».
С момента появления Go в 2009 году его разработчики ввели несколько изменений в способ организации кода и его зависимостей. Из-за этого вы можете найти множество противоречивых рекомендаций, большая часть которых уже устарела (например, смело игнорируйте обсуждения GOROOT и GOPATH).
В контексте современных разработок на Go действует простое правило: можете организовывать свои проекты любым удобным вам способом и хранить их в любом удобном месте.
Рассмотрим основы написания программы на Go. По ходу дела вы увидите, из каких частей состоит простая программа на Go. Возможно, вы еще не все поняли, но это нормально — для этого и предназначена остальная часть книги!
Первое, что вам нужно сделать, — создать каталог для хранения своей программы. Назовем его ch1. В командной строке введите новый каталог. Если в терминале вашего компьютера используется командная оболочка bash или zsh, это будет выглядеть следующим образом:
$ mkdir ch1
$ cd ch1
Внутри каталога выполните команду gomodinit, чтобы отметить его как модуль Go:
$ go mod init hello_world
go: creating new go.mod: module hello_world
Подробнее о том, что такое модуль, вы узнаете в главе 10, а пока достаточно знать, что проект Go называется модулем. Модуль — это не просто исходный код, это еще и точная спецификация зависимостей кода внутри модуля. В корневом каталоге каждого модуля есть файл go.mod. Выполнение команды gomodinit создает этот файл. Содержимое базового файла go.mod выглядит следующим образом:
module hello_world
go 1.20
В файле go.mod указываются имя модуля, минимальная поддерживаемая версия Go для него, а также любые другие модули, от которых зависит ваш модуль. Можно считать, что он похож на файл requirements.txt, используемый в Python, или Gemfile, применяемый в Ruby.
Вам не следует редактировать файл go.mod напрямую. Вместо этого используйте команды goget и gomodtidy для управления изменениями в файле. Повторюсь: все, что связано с модулями, рассматривается в главе 10.
Теперь давайте напишем код! Откройте текстовый редактор, введите следующий текст:
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
и сохраните его в каталоге ch1 в файле с именем hello.go. (Да, отступы в примере выглядят неаккуратно: я хотел сделать именно так! Сейчас вы поймете почему.)
Давайте быстро пройдемся по частям созданного вами файла Go. Первая строка — это объявление пакета. Внутри модуля Go код объединен в один или несколько пакетов. Главный пакет в модуле Go содержит код, который запускает программу Go.
Далее следует объявление об импорте. В инструкции import перечисляются пакеты, на которые ссылается данный файл. Вы используете функцию из пакета fmt (обычно произносится как «фампт») из стандартной библиотеки, поэтому указываете этот пакет здесь. В отличие от других языков, Go импортирует только целые пакеты. Вы не можете ограничить импорт определенными типами, функциями, константами или переменными внутри пакета.
Все программы на Go запускаются из функции main в пакете main. Вы объявляете эту функцию, введя funcmain() и открывающуюся фигурную скобку. Как и в Java, JavaScript и C, в Go для обозначения начала и конца блоков кода используются скобки.
Тело функции состоит из одной строки. В ней говорится, что вы вызываете функцию Println из пакета fmt с аргументом "Hello,world!". Как опытный разработчик, вы, скорее всего, можете догадаться, что делает вызов этой функции.
После сохранения файла вернитесь в терминал или командную строку и введите:
$ go build
Это создаст исполняемый файл с именем hello_world (или hello_world.exe в Windows) в текущем каталоге. Запустите его, и, как ни удивительно, вы увидите на экране надпись Hello,world!:
$ ./hello_world
Hello, world!
Имя этого двоичного файла совпадает с именем файла или пакета в объявлении модуля. Если вам нужно сохранить приложение под другим именем или в другом каталоге, используйте флаг -o. Например, чтобы скомпилировать код в двоичный файл с именем hello, нужно ввести следующую команду:
$ go build -o hello
В разделе «Тестирование небольших программ с помощью go run» главы 11 я расскажу о другом способе выполнения программы на Go.
Создатели языка Go прежде всего хотели создать язык, который позволял бы писать код эффективно. Это означало, что они должны были использовать простой синтаксис и быстрый компилятор. Кроме того, это вынудило создателей языка Go пересмотреть подход к форматированию кода. В то время как другие языки предоставляют вам большую свободу в выборе способа форматирования кода, Go не делает этого. Он обязывает использовать стандартный формат, что существенно облегчает написание инструментов для работы над исходным кодом. Это упрощает компилятор и делает возможным создание продвинутых генераторов кода.
У этого подхода есть и еще одно преимущество. Раньше разработчики тратили очень много времени на «войну форматов». Благодаря тому что Go определяет стандартный способ форматирования кода, Go-разработчикам не приходится спорить относительно того, какой стиль размещения фигурных скобок лучше использовать или как лучше задавать отступы (https://oreil.ly/dAsbS): с помощью символов табуляции или пробелов (https://oreil.ly/dSkol). Так, например, для задания отступов в Go-коде применяются символы табуляции, и если открывающая фигурная скобка не находится в той же строке, что и начинающие этот блок команда или объявление, это считается ошибкой синтаксиса.
Среди Go-разработчиков бытует мнение, что создатели языка Go решили использовать стандартный формат для того, чтобы исключить споры о формате, и уже после этого обнаружили преимущества данного подхода в плане создания инструментов. Однако Расс Кокс (Russ Cox), ведущий разработчик Go, публично заявил о том, что его исходным мотивом было упрощение процесса создания инструментов (https://oreil.ly/rZEUv).
В набор средств разработки языка Go входит команда gofmt, которая автоматически исправляет пробелы в вашем коде в соответствии со стандартным форматом. Однако она не может исправить фигурные скобки в неправильной строке. Запустите эту команду следующим образом:
$ go fmt ./...
hello.go
Символы ./... указывают инструменту Go применить команду ко всем файлам в текущем каталоге и во всех подкаталогах. Вы увидите это еще не раз, когда будете знакомиться с другими инструментами Go.
Если вы откроете файл hello.go, то увидите, что строка с fmt.Println теперь имеет правильный отступ с одной табуляцией.
Не забудьте запустить gofmt перед компиляцией кода и как минимум перед внесением изменений исходного кода в свой архив данных! А если вдруг забыли, сделайте отдельную операцию фиксации изменений, которая выполняет только gofmt ./..., чтобы не скрывать логические изменения в лавине изменений форматирования.
Правило вставки точки с запятой
Команда gofmt не исправляет ошибочное размещение фигурной скобки не в той строке, что объясняется наличием правила вставки точки с запятой. Подобно языкам C и Java, Go требует, чтобы каждый оператор заканчивался символом точки с запятой. Однако Go-разработчики не должны расставлять символы точки с запятой вручную. Компилятор языка Go делает это автоматически, следуя очень простому правилу, суть которого изложена в кратком руководстве «Эффективный Go» (https://oreil.ly/hTOHU).
Если символу новой строки предшествует одна из следующих лексем:
• идентификатор, включая такие слова, как int и float64;
• один из базовых литералов, таких как число или строковая константа;
• лексемы break, continue, fallthrough, return, ++, ––, ), или },
то лексический анализатор вставляет после нее символ точки с запятой.
Зная, что в Go действует это простое правило, легко понять, почему невозможно исправить размещение в неправильном месте фигурной скобки. Если, например, вы напишете следующий код:
func main()
{
fmt.Println("Hello, world!")
}
то благодаря правилу вставки точки с запятой будет распознан символ ) в конце строки funcmain(), а код приведен к следующему виду:
func main();
{
fmt.Println("Hello, world!");
};
а это некорректно.
Правило вставки точки с запятой и связанное с ним ограничение на размещение скобок — одна из тех вещей, которые делают компилятор языка Go проще и быстрее, в то же время обеспечивая единый стиль программирования, что весьма и весьма разумно.
В одном из классов ошибок код синтаксически корректен, но, скорее всего, неверен. Инструмент go включает команду govet для обнаружения ошибок такого рода. Добавьте одну из них в программу и посмотрите, как она будет обнаружена. Измените строку fmt.Println в hello.go на следующую:
fmt.Printf("Hello, %s!\n")
Команда fmt.Printf похожа на printf в C, Java, Ruby и многих других языках. Если вы раньше не встречались с fmt.Printf, то это функция с шаблоном в качестве первого параметра и значениями для заполнителей в шаблоне в остальных параметрах.
В этом примере у вас есть шаблон ("Hello,%s!\n") с заполнителем %s, но для него не указано значение. Этот код скомпилируется и запустится, но он не будет корректным. Одна из вещей, которую определяет govet, — это наличие значения для каждого заполнителя в шаблоне форматирования. Запустите govet на измененном коде, и он обнаружит ошибку:
$ go vet ./...
# hello_world
./hello.go:6:2: fmt.Printf format %s reads arg #1, but call has 0 args
Теперь, когда govet нашел ошибку, вы можете легко ее исправить. Измените строку 6 в hello.go на следующую:
fmt.Printf("Hello, %s!\n", "world").
Несмотря на то что govet выявляет несколько распространенных ошибок программирования, есть вещи, которые он не может обнаружить. К счастью, сторонние инструменты для проверки качества кода Go могут восполнить этот пробел. Некоторые из наиболее популярных инструментов для проверки качества кода рассматриваются в разделе «Использование сканеров качества кода» главы 11.
Точно так же, как вы должны выполнить gofmt, чтобы убедиться, что код отформатирован правильно, выполните govet, чтобы проверить наличие возможных ошибок в корректном коде. Эти команды — лишь первый шаг в обеспечении высокого качества вашего кода. В дополнение к советам из этой книги всем разработчикам Go следует ознакомиться с руководством «Эффективный Go» (https://oreil.ly/GBRut) и страницей комментариев к обзору кода на вики-странице Go (https://oreil.ly/FHi_h), чтобы понять, как выглядит идиоматический код Go.
Хотя, как вы уже успели убедиться, написать небольшую программу на Go можно, используя только текстовый редактор и команду go, для работы над более крупными проектами вам, вероятно, потребуются продвинутые инструменты. Интегрированные среды разработки для Go предоставляют множество преимуществ по сравнению с текстовыми редакторами, включая автоматическое форматирование при сохранении, завершение кода, проверку типов, создание отчетов об ошибках и интегрированную отладку. К настоящему времени уже созданы отличные средства поддержки языка Go (https://oreil.ly/cav8N) для большинства существующих текстовых редакторов и интегрированных сред разработки. Если вы еще не определились с выбором среды разработки, то знайте, что двумя наиболее популярными вариантами в случае языка Go являются редактор кода Visual Studio Code и интегрированная среда разработки GoLand.
Если вы хотите найти бесплатную среду разработки, то лучшим выбором будет редактор кода Visual Studio Code компании Microsoft (https://oreil.ly/zktT8). За время, прошедшее с момента его появления в 2015 году, VS Code успел приобрести чрезвычайно большую популярность среди разработчиков. Хотя поддержка языка Go не входит в его «комплект поставки», его можно превратить в среду разработки для языка Go, скачав расширение для поддержки этого языка из галереи расширений.
Поддержка языка Go в редакторе VS Code обеспечивается с помощью сторонних расширений, доступ к которым осуществляется через встроенный рынок программного обеспечения. К ним относятся инструменты для разработки языка Go, отладчик Delve (https://oreil.ly/sosLu) и gopls (https://oreil.ly/TLapT) — языковой сервер для языка Go, созданный командой разработчиков этого языка. При этом компилятор для Go вы должны установить самостоятельно, а Delve и gopls для вас установит Go-расширение редактора.
Что такое языковой сервер? Это стандартная спецификация API, позволяющего редакторам реализовать такие интеллектуальные функции редактирования, как автозавершение кода, проверки качества или поиск всех мест, где переменная или функция используется в вашем коде. Для получения более подробной информации о языковых серверах и их возможностях посетите веб-сайт Language Server Protocol (https://oreil.ly/2T2fw).
Установив и настроив инструменты, можете открыть свой проект и приступить к работе над ним. Окно вашего проекта должно выглядеть примерно так, как показано на рис. 1.1. Основы работы с Go-расширением редактора VS Code демонстрируются во вводном видео «Приступая к работе с VS Code Go» (https://oreil.ly/XhoeB).
Рис. 1.1. Visual Studio Code
GoLand (https://oreil.ly/6cXjL) — это ориентированная на язык Go интегрированная среда разработки (IDE) компании JetBrains. Хотя компания JetBrains славится в первую очередь своими инструментами для разработки на Java, это не мешает GoLand быть прекрасной средой разработки для языка Go. Как можно убедиться, взглянув на рис. 1.2, пользовательский интерфейс среды разработки GoLand выглядит практически так же, как интерфейс сред разработки IntelliJ, PyCharm, RubyMine, WebStorm, Android Studio и любой другой IDE от компании JetBrains. Поддержка Go в GoLand включает в себя такие возможности, как рефакторинг, выделение синтаксиса, автодополнение и навигация по коду, всплывающие подсказки с описанием типов и функций, отладчик, отслеживание покрытия кода и многое другое. Помимо поддержки языка Go, среда разработки GoLand предлагает также инструменты для работы с JavaScript/HTML/CSS и базами данных SQL. В отличие от редактора кода VS Code, для использования среды разработки GoLand вам не потребуется установка подключаемого модуля.
Рис. 1.2. GoLand
Если у вас уже есть подписка на IntelliJ IDEA Ultimate, можете добавить в нее поддержку Go, установив соответствующий плагин. Хотя GoLand — это коммерческое программное обеспечение, у JetBrains есть бесплатная лицензионная программа для студентов и разработчиков основного открытого исходного кода. Если вы не подходите под условия бесплатной лицензии (https://oreil.ly/48gEF), можете поработать с 30-дневной бесплатной пробной версией. После этого за использование GoLand придется платить.
Существует еще один важный инструмент для разработки на языке Go, который к тому же не требует установки. Перейдя по адресу http://play.golang.org, вы попадете на страницу онлайн-песочницы для языка Go, внешний вид которой показан на рис. 1.3. Если вам приходилось использовать такие инструменты командной строки, как irb, node или python, то вы увидите, что работа с этой онлайн-песочницей осуществляется во многом так же. Она позволяет вам запускать и показывать другим пользователям небольшие программы. Введите свою программу в поле ввода и нажмите кнопку Run (Выполнить) для ее выполнения. Нажатие кнопки Format (Форматировать) запустит для программы команду gofmt и обновит операторы импорта. Кнопка Share (Поделиться) позволяет создать уникальный URL-адрес для того, чтобы предоставить ссылку на программу другим пользователям или вернуться к работе над ней в дальнейшем (хоть и было доказано, что эти ссылки сохраняются в течение долгого времени, я все же не стал бы полагаться на онлайн-песочницу в качестве репозитория исходного кода).
Рис. 1.3. Онлайн-песочница
Как показывает рис. 1.4, вы можете сымитировать работу с несколькими файлами, отделив каждый файл с помощью строки вида ––filename.go--. Можете даже создавать имитируемые подкаталоги, включив в имя файла символ /, например --subdir/my_code.go--.
Рис. 1.4. Онлайн-песочница поддерживает использование нескольких файлов
Задействуя онлайн-песочницу, не забывайте о том, что она работает на другой машине (если точнее, на машине компании Google), что ограничивает вашу свободу действий. Это дает возможность выбрать из нескольких версий Go (обычно это текущая версия, предыдущая версия и последняя версия разработки). Вы можете устанавливать сетевые соединения только с localhost, а процессы, которые выполняются слишком долго или задействуют слишком много памяти, останавливаются. Если в вашей программе используется время, установите в качестве начала отсчета 10 ноября 2009 года, 23:00:00 UTC (это дата и время первой официальной презентации языка Go). Даже эти ограничения не мешают онлайн-песочнице быть полезным инструментом, который позволяет опробовать новые идеи, не создавая новый проект на своей машине. В книге я буду часто ссылаться на онлайн-песочницу, чтобы вы могли запускать примеры кода, не копируя их на свой компьютер.
Никогда не размещайте в онлайн-песочнице такую конфиденциальную информацию, как ваши личные сведения, пароли и секретные ключи! Если вы нажмете кнопку Share (Поделиться), то эта информация будет сохранена на серверах компании Google и станет доступной для всех пользователей, получивших соответствующую ссылку. Если вы по ошибке предоставили доступ к такой информации, свяжитесь с компанией Google по адресу [email protected] и сообщите, какой URL-адрес вам нужно удалить и по какой причине это нужно сделать.
IDE удобно использовать, но трудно автоматизировать. Сегодня процесс программной разработки подразумевает применение воспроизводимых и автоматизируемых операций сборки, которые может выполнять кто угодно, где угодно и когда угодно. Работа с такого рода инструментарием — хорошая практика разработки программного обеспечения. Это позволяет избежать извечной ситуации, когда разработчик снимает с себя ответственность за любые проблемы при сборке, пожимая плечами и заявляя: «На моей машине все работает!» Реализовать такой подход можно с помощью скрипта, в котором будут определены этапы процесса сборки. Go-разработчики для этой цели используют утилиту make. Она позволяет разработчикам определить набор операций, необходимых для создания программы, и порядок, в котором эти шаги должны выполняться. Если вы не знакомы с этой утилитой, напомню, что она с 1976 года применяется для сборки программ в операционных системах Unix.
В каталоге ch1 создайте файл Makefile с таким содержимым:
.DEFAULT_GOAL := build
.PHONY:fmt vet build
fmt:
go fmt ./...
vet: fmt
go vet ./...
build: vet
go build
Даже если вам не приходилось работать с Make-файлами раньше, будет совсем не трудно разобраться в том, что здесь происходит. Каждая из выполняемых операций называется целью. Директива цели по умолчанию .DEFAULT_GOAL указывает, какая цель должна выполняться в том случае, если не будет указано ни одной цели. В данном случае в качестве цели по умолчанию задана операция build. Далее следуют определения целей. В каждом из них сначала указывается имя цели, а за ним после знака двоеточия (:) — имена целей, запущенных перед выполнением данной цели (как, например, vet в определении build:vet). Задачи, выполняемые целью, находятся в строках с отступом после цели. Директива фиктивной цели .PHONY не дает утилите make запутаться в том случае, если в вашем проекте будет создан каталог с таким же именем, как у одной из перечисленных целей.
Запустите утилиту make, и вы увидите следующий результат:
$ make
go fmt ./...
go vet ./...
go build
Ввод всего одной команды обеспечивает правильное форматирование кода, проверяет его на наличие неочевидных программных ошибок и компилирует. Вы также можете проверить код с помощью команды makevet или только средство форматирования — командой makefmt. Возможно, это и нельзя назвать значительным улучшением, однако гарантированный запуск средств форматирования и статического анализа перед тем, как разработчик (или скрипт, запущенный сервером непрерывной интеграции) запустит операцию компиляции, означает, что вы никогда не пропустите ни одного шага.
Одним из недостатков Make-файлов является то, что они требуют определенной внимательности: каждую из указанных для цели задач нужно обязательно снабдить отступом с помощью символа табуляции. К тому же поддержка этих файлов не входит в число стандартных возможностей операционной системы Windows. Если вы собираетесь писать Go-код на машине с Windows, сначала потребуется установить утилиту make. Самый простой способ это сделать — сначала установить менеджер пакетов наподобие Chocolatey (https://chocolatey.org), а затем с его помощью установить утилиту make (в случае Chocolatey это можно сделать с помощью команды chocoinstallmake).
Если вы хотите больше узнать о написании Make-файлов, есть хорошее руководство (https://oreil.ly/Vytcj) от Чейза Ламберта (Chase Lambert), но в нем для объяснения концепций в некоторых случаях используется язык C.
Код из главы 1 вы найдете в репозитории к этой книге: https://oreil.ly/eOfkK.
Как и в случае любого другого языка программирования, средства разработки языка Go регулярно подвергаются изменениям. Начиная с версии Go 1.2 новые релизы выходят с интервалом примерно 6 месяцев. По мере необходимости также выпускаются релизы с исправлениями программных ошибок и проблем безопасности. В силу того что команда разработчиков языка Go применяет быстрые циклы разработки и старается обеспечивать обратную совместимость, релизы языка Go обычно имеют инкрементный характер и вносят не слишком много изменений. В статье Go 1 and the Future of Go Programs (https://oreil.ly/p_NMY) подробно объясняется, каким образом команда разработчиков языка Go планирует не допускать изменений, способных нарушить работоспособность имеющегося Go-кода. Там говорится, что команда разработчиков не будет вносить в язык или стандартную библиотеку изменения, ломающие обратную совместимость, в любой версии языка Go, начинающейся с 1, за исключением изменений, необходимых для исправления программных ошибок или проблем безопасности. Во вступительной речи на конференции GopherCon 2022 (https://oreil.ly/Ohkr7) Расс Кокс рассказал, каким образом команда разработчиков Go работает над тем, чтобы код Go не ломался. Он сказал: «Я считаю, что приоритет совместимости был самым важным дизайнерским решением, которое мы приняли в Go 1».
Эта гарантия не распространяется на команды go. Во флаги и функциональность команд go уже вносились несовместимые изменения, и вполне возможно, что это произойдет снова.
Программы на Go компилируются в отдельный двоичный файл, поэтому не нужно беспокоиться о том, что обновление среды разработки может привести к сбою в работе ваших развернутых программ. На одном компьютере или виртуальной машине могут одновременно работать программы, скомпилированные с помощью разных версий Go.
Когда будете готовы к тому, чтобы обновить установленные на вашей машине средства разработки языка Go, проще всего это будет сделать на платформах Mac и Windows. Если вы производили установку с помощью менеджера пакетов brew или chocolatey, то с его помощью можно выполнить и обновление. Если же скачивали установочный пакет со страницы https://golang.org/dl, воспользуйтесь последней версией этого пакета, которая в ходе установки удалит с машины старую версию.
На машинах с Linux и BSD необходимо скачать последнюю версию, переместить старую версию в резервный каталог, распаковать новую версию и удалить старую:
$ mv /usr/local/go /usr/local/old-go
$ tar -C /usr/local -xzf go1.20.6.linux-amd64.tar.gz
$ rm -rf /usr/local/old-go
Технически вам не нужно перемещать существующую версию в другое место — можете просто удалить ее и установить новую версию. Однако это действие относится к категории «лучше перестраховаться, чем потом жалеть». Если при установке новой версии что-то пойдет не так, хорошо, если предыдущая версия будет под рукой.
В конце каждой главы приведены упражнения, которые позволят вам опробовать идеи, о которых я рассказываю. Ответы на эти упражнения вы найдете в папке ch01 в репозитории к книге: https://oreil.ly/c-oc3.
1. Возьмите программу «Hello, world!» и запустите ее в онлайн-песочнице The Go Playground. Поделитесь ссылкой на код в онлайн-песочнице с коллегой, который хотел бы познакомиться с языком Go.
2. Добавьте в Make-файл цель clean, которая удаляет бинарный файл hello_world и любые другие временные файлы, созданные с помощью gobuild. Просмотрите документацию по командам Go (https://oreil.ly/uqsMy), чтобы найти команду go, которая поможет это реализовать.
3. Поэкспериментируйте с изменением форматирования в программе «Hello, world!». Добавьте пустые строки, пробелы, измените отступы, вставьте новые строки. После внесения изменений запустите gofmt, чтобы проверить, не отменилось ли изменение форматирования. Также запустите gobuild, чтобы проверить, компилируется ли код по-прежнему. Вы также можете добавить дополнительные вызовы fmt.Println, чтобы увидеть, что произойдет, если поместить пустые строки в середину функции.
В этой главе вы узнали, как установить и настроить среду разработки для языка Go, а также изучили инструменты для компиляции Go-программ и обеспечения хорошего уровня качества кода. Теперь, когда у вас есть готовая среда, можем перейти к следующей главе, где рассмотрим встроенные типы языка Go и способы объявления переменных.