На Go непривычно после Python
На работе переводим сервисы на Go. Делюсь ощущениями от Go, как FastAPI-питонист:
В Go классов нет, есть
structс полями.Внутри структур нет методов. Перечислили поля и все. Дальше функцию связываем отдельно со структурой сигнатурой вида
funс (s *SomeStruct) Greet () string {}. С аргументами читается еще тяжелее.ООП нет, наследования нет. Связь между структурами через композицию.
Ошибки нужно обрабатывать руками без
try ... exceptс помощьюif err != nil {...}.nilвместоNoneЭксепшнов нет. Функции возвращают ошибку как обычное значение:
val, err := SomeFunc(). Хотя в Python я ответ из кортежей прям не люблю и избегаю, тут это база.Зато есть
panic, которые по сути – необработанные эксепшны.Но на паники есть
recover, который лечит последствия паники :)Комментарии через два слеша
// commentДокстринги над сигнатурами, а не под.
OpenaAPI для Swagger надо собирать самому без FastAPI. Напрочь забытый навык. Даже с либами вроде
swaggo/swagделать это надо руками, с ошибками.Валидации полей нужно писать руками. Нет аналога
Pydanticс батарейками.Строка в двойных кавычках
"w"– строка. В одинарных'w'– руна, другой тип данных, который принимает в себя только один символ. Писать слово или фразу в руну нельзя.А есть еще backtick ` ` для тегов структур. В них как раз могут задаваться правила валидаций в
go-playground/validator:type User struct {
Name string `validate:"required,min=2"`
}lenу строк в байтах. Символ в кириллице = 2 байта.lenстроки на кириллице ~х2, непривычно. Нужно считать длину рунами в строках.Иинтерполяция делается через
fmt.Printf(). В отличие от f-строк в Python требует в конце явного перевода строки с\n, иначе строки слипаются.Вместо snake_case – lowerCamelCase для приватных идентификаторов пакета, а UpperCamelCase для экспортируемых.
Первым аргументом в запускаемом приложении командой
go run some-script.goнеявно выступает путь до файла. Из-за этого появляются идиомы в циклах типо «начни со 2-го аргумента».Моржовый оператор
a := "some"в Go это инициализация переменной с присваиванием. В Python это оператор вif ... elseблоках, который инициализирует переменную только если сработало условие.Аргументы у методов – позиционные.
DoSomething(first, second, last)противdo_something(action=first, modifier=second, final_action=last)у Python. Python умеет в лаконичность, но тут Go в нее заставляет. У методов со сложными контрактами надо сигнатуру подсматривать.
Что в Go нравится:
Тут много наивного по неопытности :)
Горутины – топ. Не нужно в голове держать асинхронный код, потоки, процессы, футуры, CPU-задачи, IO-задачи – на все горутины. А для передачи данных – каналы. Горутины весят 2-4 КБ против ОС-потока в 2-4 МБ памяти. Нет танцев с GIL.
go funcи начинаешь в конкурентность.Статическая типизация при сборке находит много ошибок без линтеров и
mypy. Еще она заставляет явно писать типы данных в аргументах и ответах от функций. Код нагляднее.Вместо двоеточий и отступов фигурные скобки. Я еще с NodeJS любил не капризное авто-форматирование.
Go-скрипты собираются в бинарники. Для них не нужен установленный Python или JVM. Просто запускаем как обычный баш-скрипт через
./scriptИмпортировать пакеты нужно целиком. Как в Python только метод импортировать нельзя. Обязательная лаконичность тут нравится. Импорты аккуратные, а в коде вызов их функций более явный.
Код модулей удобно читать сверху вниз. Python – интерпретируемый. Все, что не объединено в класс, должно быть объявлено перед вызовом. Код приходится нередко читать снизу вверх. Go – компилируется, порядок кода неважен. Читать код по ходу пьесы проще.
Стандартный пакет для тестирования
go testвсе умеет из коробки. Аналогpytestкак внешняя зависимость не нужен.Ради чего все это: перевод сервиса с Python на Go даже тупо с ИИ-агентом, по метрикам Prometheus (АБ 50/50 трафик) снизил время ответа и потребление CPU и IO-ресурсов в десятки раз.
Из-за последнего вас и спрашивают на Python-собесе «готов перейти на Go»? Бабки, с-ка, бабки.
