Мій Go-девелоперський щоденник: про навчання та виклики

Мене звати Петро Щербатюк, я Software Engineer у MacPaw. У цій статті я поділюся власним досвідом переходу на Go як Back-end розробник.

Дисклеймер: ця стаття не є мануалом або точним порівнянням PHP i Go. Скоріше, це ті враження, з якими ви стикнетесь, якщо вирішите перейти на іншу мову програмування.

Чому я вирішив перейти на Go

На 2023 рік ми в команді поставили собі ціль — вивчення додаткових мов програмування. На вибір було запропоновано Python, JS і, власне, Go, на якій ми й зупинилися.

Серед переваг Golang розглядалися такі:

Швидкодія.

Ми не збиралися писати справжній Highload, але якщо вже обирати нову мову для вивчення, чому не обрати щось більш ефективне?

Статична типізація.

Дозволяє виявляти помилки на етапі компіляції, а не в runtime.

Суворіша філософія написання коду ніж у PHP.

Як приклад, наведу досить поширену в PHP практику використання асоціативних масивів. Так, це можна замінити командними домовленостями про те, як робити можна, а як — ні, але деякі речі Go просто не дозволить зробити, і я вважаю, що це на краще.

Робота з великою кількістю паралельних задач.

Це було важливо для нас через специфіку проєкту. Так, для PHP є сторонні інструменти для роботи з воркерами, але хотілося спробувати мову, в якій парадигма паралелізму була закладена із самого початку.

Менторство від ініціативного колеги, який вже мав досвід роботи з Golang.

Як я вивчав Go

Я навчався за гайдом на go.dev і пройшов курс на Coursera, який радше розчарував. Також використовував ChatGPT (куди ж без нього) та навчався через зворотний зв’язок від колеги на початкових стадіях розробки.

Щодо застосування Golang, у нас була ціль зробити специфічний сервіс оновлень macOS-застосунків — розробка з нуля сервісу, який буде збирати дані від мільйонів користувачів, обробляти, доповнювати їх і повертати користувачам.

Особливості, з якими я стикнувся за час розробки на Golang

Відсутність null-values.

Як приклад, наведу парсинг JSON-запиту в структуру за допомогою стандартної бібліотеки. Якщо в запиті відсутнє конкретне поле, відповідна змінна в структурі буде заповнена дефолтним значенням.

І якщо для рядка (string) ми ще потенційно можемо вважати дефолтне значення (порожній рядок) не валідним значенням, то для інтеджерів і булевих змінних дефолтні значення — нуль і false відповідно, які цілком можуть бути валідними значеннями з реквестів.

Як варіант, можна використовувати вказівники на змінні. У такому разі, за відсутності конкретного поля ми отримаємо nil pointer, який легко можна перевірити. Але за таким сценарієм усе ще немає розуміння, чи ми отримали null значення у реквесті, чи поле в ньому було відсутнє.

Відсутність фреймворків на кшталт Laravel або Symfony.

Фреймворки на Go звісно є, але вони значно простіші порівняно з вищезгаданими PHP-аналогами. Це можна вважати і перевагою, і недоліком, але на це точно треба зважати.

Також розробка на Go схожа на порівняння MacOS і GNU- \ Linux-дистрибутивів: у першому випадку за вас усе вирішили розробники, просто сідайте і пишіть, а в другому — у вас є пʼять різних систем ініціалізації, десять різних DE, і вам треба самим збирати проєкт із цього конструктора.

Особисто мені дуже не вистачає аналогу Symfony DI і деякого вбудованого у фреймворки «цукру».

Наслідок з попереднього пункту — складніше структурування проєкту.

По-перше, через відсутність чіткої структури файлів у фреймворках її треба продумувати власноруч. Через те, що проєкт був для нас першим на Go, доводилося обирати архітектуру, не до кінця розуміючи, на які підводні камені наштовхнемося потім.

Звісно, із часом (і деякою кількістю рефакторингу) оптимальний варіант було знайдено.

По-друге, є особливості роботи з пакетами, бо кожна тека з кодом — це окремий пакет. І підтеки в пакетах — це теж окремий пакет. Спочатку ми час від часу зіштовхувалися з проблемою циклічного імпорту пакетів. Через це доводилося переносити логіку проєктом.

Обробка помилок.

Про це не написав, мабуть, лише лінивий. Якщо у PHP ви можете обернути код у try / catch, знаючи, що винятки буде оброблено, то в Go помилки мають повертатися у вигляді змінних і мають бути оброблені вручну. З одного боку, це дисциплінує і змушує писати більш усвідомлено, а з іншого — if err != nil, if err != nil, if err != nil...

Вказівники (pointers).

Завжди стежте за вказівниками.

Компіляція.

Після змін у коді ви не можете просто зробити ще один запит, щоб перевірити, чи зміни були правильними — треба чекати, поки скомпілюється проєкт. Але, з іншої сторони, цей нюанс змушує тебе бути більш уважним і двічі перевіряти, що ти написав перед запуском.

Типізація.

Здавалося б, що тут може піти не так? Але нещодавно наткнувся на те, що int у Go й у PostgreSQL різних розмірів: у Go він залежить від архітектури процесора (4 або 8 байтів). Звісно, RTFM, але тут каверзи я не очікував.

То чи варто переходити на Go

Перечитавши список, який я накидав вище, може скластися враження, що негативу більше, ніж позитиву. Проте це точно не так. Так, шишки регулярно набиваються, але це — цікавий і корисний досвід, який дозволяє поглянути на веб з іншої точки зору.

На рівні емоцій вивчення нової мови взагалі перенесло мене в часи написання лабораторних в університеті.

Якщо ж відкинути лірику, то скажу, що у виборі / не виборі Go для розробки варто відштовхуючись від задачі. Чи писав би я на Go просте API з невеликою кількістю бізнес-логіки? Ні, бо PHP був би тут виграшним через швидкість і простоту розробки.

Чи писав би я якийсь мікросервіс з більш-менш складною бізнес-логікою, особливо, якщо вона вимагає великої кількості обчислень? Hell, yes. А якщо логіку ще можна розпаралелити, то тут і думати не варто.

Наш внутрішній експеримент я вважаю успішним, адже сервіс зараз у стадії альфа-релізу, і сподіваюся, що він проживе довге і щасливе життя, радуючи розробників і наших клієнтів. Окремо хотів би подякувати MacPaw за можливість свічнутися, це було неочікувано навіть для самого себе.

👍ПодобаєтьсяСподобалось18
До обраногоВ обраному5
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Якщо хтось планує вивчати Go, або вже вивчає, спробуйте цей ресурс — quii.gitbook.io/learn-go-with-tests, можливо допоможе вам простіше і цікавіше вивчати Go)

Йду тим самим шляхом... Флешбекаю Делфі та сумую за Ларавел. Ще досить неочікувано що в функціях нема дефолтних значень

за чим найбільше у ларі сумуєте, якщо можна виділити конкретні пункти?

Прикольно 👍
Сам слідкую за Го, намагаюсь освоїти «для себе»

Будь ласка, чи можна трохи детальніше розповісти про порядок вивчення?
Бо офіційний go.dev трохи «хто в ліс, хто по дрова» — якогось строго визначеного порядку на go.dev/learn нема, починай з чого хочеш.

І наприклад, чи є помічним Effective Go go.dev/doc/effective_go ?

Також знайшов таку штуку — roadmap.sh/golang — чи бачив-пробував її хтось?

роудмапа не зовсім актуальна, там є багато зайвого і того, що не пройшло перевірку часом

Якогось конкретного набору ресурсів нажаль описати не зможу. Починав на go.dev, продовжив на курсері, після чого одразу перейшов до написання проекту. На початку з код-ревʼю мені допомогав ментор, підкидав ліби якими можна замінити написані велосипеди. Частина знань — це коли впирався в якусь конкретну проблему і гуглив повʼязані із цим статті. Також для поверхневого огляду мови (або як шпаргалка) непоганий ресурс gobyexample.com

мені дуже подобається ця збірка статей, книг, курсів. Все згруповано по темам
mehdihadeli.github.io/awesome-go-education

Я свічнувся років п’ять назад. Зараз читаю це і згадую себе, «молодого гошніка». На справді ви будете крінжувати з цієї своєї статі через деякий час, бо все що ви написали — не вірно.

Допускаю що так воно може бути, у статті скоріш хотів описати саме перші враження від переходу, впевнений із часом погляди на мову зміняться

все що ви написали — не вірно.

Ну так написали б хоч в двох словах по кожному пункту спростування. Ну йо ма йо, ну зараз це ж як «ви неправі, але чому — я не скажу»)

Это очень круто, что вы наконец перешли на Go! Теперь сможете писать реально высокопроизводительный и реально многопоточный код, а не так как это было в php.

здоров) приємно що не забуваєте)

мене інше цікавить, як людині в якой з GO є тількі півтора десятка
літкод хардов 7ми летней давності може щось знайти на існуючому
ринку (де навіть для джунов потрібні 5-10+ років досвіду саме на Го)

Є вакансії з хорошими умовами та успішно закриваються досить швидко

А є вакансії «розробити соціальну мережу на Go за $100» які висять місяцями та створюють таке враження про ринок, як ви описали в коментарі

Також можу додати варіант із поступовим свічом, але це залежить від позиції і компанії

Як вважаєте, ви тепер можете повністю перейти на позицію Go Software Engineer? Я теж думаю свічнутися, цікаво за який час вийде це зробити повністю. Але я .NET розробник

У .NET розробників все гаразд з технологіями тому перехід з .NET на Go то хіба заради екзотики або спробувати щось нове

З технологіями все ок, але так, якшо робити перехід, то заради екзотики і більшої зп 😅

Перехід з PHP, Python, Node.js, Ruby та Perl на Go це підвищення рівня кваліфікації та підвищення рівня винагороди
Після переходу можливе просідання винагороди, але за півроку-рік вже будете заробляти більше
Враховуючи річне просідання то моя перекваліфікація з PHP на Go окупилась приблизно за два роки

Переходити з C# на Go зараз виглядає більше як бажання щось змінити у житті, окупиться вже за два-три роки

Переходити з C# на Rust виглядає складніше, але перспективніше, на LinkedIn Learning є півторагодинний курс «Rust for C# Developers», напишіть мені в особисті то відправлю вам доступ до цього курсу

Повністю — думаю що ні, прийнанні не відчуваю впевненості у цьому. Думаю що із роком досвіду вже можна було б свічнутися

Мені було боляче після c#, потім потикав раст і зрозумів що то те що треба

го та пых вони більше доповнюють один одного ніж заміняють

ще краше комбо пых + го + фулл стек джаваскрипт будете як на гавайских хвилях кайфувати

пых як пітон, чи джава є фаундейшен до якого прокручуються аддони / чи як спойлери(обвіси) на тачку з інших мов

якщо простіше то сама мова ще має цільове призначення у такому процесі як створення програмного забезпечення

можливо так, проте мені здається що на вивчення + актуалцізацію багато ресурсів може піти

Чи писав би я на Go просте API з невеликою кількістю бізнес-логіки? Ні, бо PHP був би тут виграшним через швидкість і простоту розробки.

Якщо ви так пишете то у вас замало досвіду з Go щоб розробляти швидко у комфортному темпі

Або у мене замало досвіду з PHP

то просто PHPсти звикли до фреймворків з built-in ОРМ, тому думають, що якщо в го не так (нема Лаварелю з ормкою), то це довго. Я допомагав у переході з PHP на Go, тому стикався з таким твердженням

Запевняю вас апіху можна і без цього підняти досить швидко. РНР буквально для цього створений.

Запевняю вас, що PHP був створений не для цього. PHP був сстворений як шаблонізатор для html. Ви не вийдете в прод з PHP без хоч якогось фрейворку(люмен, сайлекс, лара, сімфоні), а якщо і вийдете, то потім не знайдете людей, які погодться це підтримувати, бо клеймо «самопіс» буде з вами довго.

Все простіше з go. Підтягнули дравер для сховища і в добру дорогу з вашим апі

Досвіду дійсно небагато, та і пхп-фреймворки більш всеохоплюючі за функціоналом, імхо

Стосовно PHP-каркасів то погоджуюсь, бачив пару відео й статей то дійсно всеохоплюючі з легким підключенням платіжних систем через плагіни

Просте API на Go: 1 файл 0 залежностей, просте API на PHP: фрейворк + тона конфігурації + менеджер процесів + реверс проксі ( fpm + nginx) ...

Погоджуюсь, для мене u8views.com це просте API, без Nginx, HTTPS за допомогою golang.org/x/crypto/acme/autocert

на го більше свободи що в відкривае більше можливостей для помилок (мова не про типізовані помилки) а щось алогічне згідно єкспектид та актуал поведінці

Software Engineer у MacPaw

не знав, що у MacPaw пишуть на го, це круто)

На DOU була вакансія /companies/macpaw/vacancies/153976/, але я дізнався що у MacPaw пишуть на Go на зустрічі спільноти RustUkraine

Диверсифікуємо знання потроху)

наткнувся на те, що int у Go й у PostgreSQL різних розмірів

Якщо подобається писати запити ручками то є type-safe кодогенерація sqlc

Після змін у коді ви не можете просто зробити ще один запит, щоб перевірити, чи зміни були правильними — треба чекати, поки скомпілюється проєкт.

Пишіть тести на прості варіанти

Але за таким сценарієм усе ще немає розуміння, чи ми отримали null значення у реквесті, чи поле в ньому було відсутнє.

У Go є json.RawMessage для подібної точності та map[string]interface{}

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

Є багато аналогів і github.com/valyala/fastjson навіть швидший (правда єбатні більше)
P.s Уточнюю ТЗ — парсер теж має мати потенційні ФСБшні бекдори? бо нагадую що mail.ru це державна контра країни терориста

годна штука, отби тільки не фсбшний мейл ру)

Хм, ось це трохи бентежить, якась анархія. Схоже на php початку/середини 2000-х, коли кожен робив як хотів, ніяких стандартів, фреймворків, кожен проект унікальний. Виглядає що Go цей шлях зараз проходить.

Мені теж так трохи здалося. Позиція розробників самої мови — залишати у ній необхідний мінімум інструментів. Для кожного розробника цей рівень різний, і коли його не вистачає — за функціоналом треба іти у відкритий світ, де є кілька реалізацій одного і того самого функціоналу. Не кажу що це погано, але іноді не вистачало якогось вбудованого цукру

Ну я не думаю що це завдання мови чи core-розробників самої мови, скоріше ком’юніті. Все ж таки go lang це мова загального призначення, хочеш базу данних роби, хочеш новий cloud типу aws чи домашню сторiнку кота Васі.
Під всі задачі не зробиш фрейворків на всі випадки. Але є типові речі, які в інших технологіях є дуже популярними і вирішують схожі задачі — laravel, django, rails, express, .net core, spring і т.д.
Впевнений що і в go lang щось подібне з’явиться. В 2000-х сам писав фреймворк свій на php, це вже потім почали з’являтись kohana, yii. Тобто зовсім з нуля щось писати проблем нема, але нахіба :)

Це не анархія. Просто декілька різних підходів до вирішення певних проблем, як наприклад парсінг різнотипного JSON, або нестачі швидкості при маршеленгу чи анмаршеленгу. А так просто береш стандартний маршелер і все(там вже v2 потрохи готують).
Якщо порівнювати підходу між golang та php, то тут більше схоже на той-же slim framework як основа там компоненти symfony які тобі потрібні, то в golang нас тут std і бібліотеки. А ось всяких фреймфорків як laravel чи symfony, думаю, в golang не з’явиться.

А ось всяких фреймфорків як laravel чи symfony, думаю, в golang не з’явиться

Думаю для web/api задач щось з’явиться, подивимось.
Бо по сутi зараз i так кожeн будує свiй мiкро-фрeймворк з std та зовнiшнiх бiблioтeк та потiм його пeрeвикористовує для iнших проeктiв. Алe нeма докумeнтацiї, best practices, покриття тeстами (залeжить вiд якостi лiб), функцiоналу можe нe вистачати якщо шаг влiво, шаг вправо.

Просто декілька різних підходів до вирішення певних проблем, як наприклад парсінг різнотипного JSON,

Ну, виглядає як якась дічь, якщо чесно. Парсинг JSON здається настільки базовою штукою, що аж дико, що в GO для цього цілий зоопарк способів.

дякую, ознайомлюся) проблема вичитування різнотипного json-у теж стояла під час розробки

Підписатись на коментарі