Последние несколько месяцев я по уши в написании и переписывании сервисов на Голанге. Будь то перенос службы с NodeJs или просто реструктуризация наспех созданного пакета Go, было очень весело изучить и разработать метод работы, который делает процесс разработки быстрее и интуитивнее каждый раз, когда я начинаю. Я получил огромное удовольствие от этой кривой обучения, и вот некоторые из моих уроков и опыта, которые другие могут поразмышлять и обсудить.

Напишите идиоматический код

Это само собой разумеется. Одним из очень важных аспектов языка является его настойчивое стремление делать все «правильно». От того, как проекты golang структурированы до строгости в линтинге и документации, каждый аспект Golang, если он сделан правильно, восхитительно интуитивно понятен и эргономичен.

Написание хорошего кода на Голанге - это не просто выражение вашей мысли или идеи в виде алгоритма. Если вы возьмете работающую функцию C / C ++ / Java и переведете ее на Golang, маловероятно, что это даст отдаленно приличный код Golang. Чтобы действительно извлечь максимум из того, что может предложить язык, нужно сначала понять его нюансы.

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

Вы можете легко найти плагины / расширения / линтеры, которые помогут улучшить качество кода Golang, который вы пишете, и мне лично нравится использовать VSCode с его расширением Golang. Он быстрый, красивый и достаточно многофункциональный для большинства случаев использования.

Пишите самодостаточные, независимые пакеты

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

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

Для меня пакет обычно включает в себя:

  1. Типы данных, относящиеся только к этому пакету, если таковые имеются. Это включает в себя структуры, которые я хотел бы создать для обработки блокировок мьютексов на определенных локальных ресурсах.

2. Интерфейс (ы) для определения поведения и функций для выполнения логики, скорее всего, вызванных упомянутыми структурами данных. Не стесняйтесь следовать шаблонам проектирования, таким как Шаблон Строителя, чтобы помочь вам изложить основы с точки зрения типов данных и интерфейсов.

3. Функции, реализующие основную логику (очевидно). Выборочно предоставляйте функциональные возможности, которые позволят другим использовать возможности этого пакета.
Одной из функций часто является функция init() пакета, которая выполняет базовую настройку, необходимую для выполнения пакетом своих обязанностей. Установите значения по умолчанию, обновите токены, запустите фоновые подпрограммы и т. Д. Отлично работает с Singleton Pattern для выполнения одноразовых задач.

Возьмем, к примеру, структуру данного проекта. Он принадлежит службе REST, которую я сейчас пишу. Файл main.go (не показан на изображении) является началом выполнения и импортирует сервер из пакета service.

Как видите, каждая задача разделена на пакет - rethink для подключения / чтения / записи из базы данных переосмысления, auth для выполнения всей аутентификации и логики на основе токена jwt, config пакет для чтения / управления настраиваемыми файлами и т. Д. .

Теперь каждый из этих пакетов можно протестировать независимо. Обратите внимание на файл service_test.go в сервисном пакете. У вас может быть тестовый файл для каждого пакета, чтобы обеспечить тщательное модульное тестирование.

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

Используйте HTTP-клиент или напишите собственное промежуточное ПО

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

Мэт Райер прекрасно объясняет это в своих статьях, так что обязательно просмотрите их, чтобы было интересно прочитать.

По сути, идея действительно проста. Вы хотите иметь функцию, которая принимает функцию-обработчик в качестве параметра и возвращает функцию-обработчик в качестве параметра.

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

Это оказывается действительно эффективным, когда вам нужно сделать множество изменений для каждой пары запрос / ответ, которую вы обслуживаете и обрабатываете. Хотя я бы порекомендовал всем попробовать написать свое собственное промежуточное ПО, если вы хотите перейти к делу, уже существует множество отличных вариантов. Обратите внимание на Chi - легкий, надежный и удобный маршрутизатор с множеством функций и промежуточного программного обеспечения.

Пользовательский http.Client превратился в перехватчик

Чаще всего вашей производственной службе необходимо выполнять сетевые вызовы. Сетевые вызовы других API, выборка ресурсов, загрузка потоков данных и т. Д. Теперь, чтобы сделать это, вам, естественно, нужно обратиться к http пакету Golang, быстро и легко http.Post(...) и покончить с этим. Я здесь, чтобы сказать вам - НЕ НУЖНО.

Старайтесь не использовать объект по умолчанию http.Client для сетевых вызовов. Вместо этого напишите отдельную функцию, которая определяет пользовательский объект http.Client. Самое главное, я хотел бы попросить вас установить конкретный тайм-аут сети, прежде всего. Вы не поверите, но клиент по умолчанию не указывает тайм-аут. Попрощайтесь со временем отклика, если этот API погоды, который вы используете, вызывает простои.
Не верите? Прочтите эту хорошо написанную статью, которая перекликается с моими чувствами.

А что такое interceptor? Что ж, все сделано правильно, эта функция будет вашим единственным каналом, через который проходит каждый сетевой вызов, который вы когда-либо выполняли. Это может включать пользовательские конфигурации, модификации запроса / ответа, перенаправление, аутентификацию, звучит уже знакомо? Эта функция станет вашим сверхмощным пит-стопом, где вы сможете делать удивительные вещи, помимо простого звонка в сеть! Статистика, аналитика, настройка, логика перенаправления, что угодно. Пределы устанавливаются вашим творчеством.

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

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

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