Как стать автором
Обновить

Комментарии 218

непонятно как без всех этих дженериков и прочих "конструкций" вообще смогли появиться, например, linux kernel. или это еще недостаточно большой проект?

linux kernel это совсем другая эпоха программирования. сейчас эпоха скорости и удобства в написании кода ))

Странно, в статье тоже говорится об "экономии времени разработчика".

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

так а в чем проблема-то? на Go код пишется намного быстрей и удобнее чем например на C, а на более новых языках можно писать еще быстрее и удобнее чем на Go.

если бы не было эволюции экосистемы программирования, то все бы до сих пор писали на двух-трех языках со времен их создания.

в программировании ИИ помогает получать быстрое решение того, что раньше нужно было гуглить или рыть в мануалах.

Хорошо бы примеры кода для сравнения, на C, C++, Rust и Go.

Пример кода? В смысле привести код распределенной системы оперирующей петабайтами данных?

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

я с этим тоже согласен

условный Linux kernel разрабатывался энтузиастами в свободное время

это не так уже больше 15и лет. Ядро разрабатывается преимущественно сотрудниками крупных корпораций в рабочее время. Инфраструктура так же работает за счёт корпораций.

Даже энтузиастам надо на что-то жить. И соответственно тратить время на заработки, на другую жизнь, на прочая. Спрашивается: так ли много у них свободного времени в принципе?

В golang прям сильно не хватает устоявшихся практик. Плюс когда на нем начинаешь реализовывать условно clean architecure или DI хотя бы, простота языка начинает висеть гирей.

Ему не нужно ни того ни другого.

Go = vibe coding micro services

linux kernel вообще изначально был специально спроектирован без использования ООП. Думаю, что сравнивать низкоуровневые структуры ядра и бизнес-объекты энтерпрайза вообще некорректно, это абсолютно разные уровни, требующие разных подходов, вне зависимости от конечного количества строк кода в проекте.

Можно подумать в ядре нет ООП

в ядре линукса - нет

был не прав, есть

Ядро, почти целиком ООП.

На Сях, да. Концепция состояния и методов для оперирования им это и есть основа ООП. Там даже наследование есть.

Не равнозначное сравнение. Любой сервис web приложения и Linux kernel это абсолютно разные уровни, в частоте решения задач, в скорости разработки, удобстве разработки, в частоте расширения, в количестве миддл участников.

OS Kernel это другой тип кода совсем. Мы же не будем ставить на первое место скорость и удобство разработки в, к примеру, базах данных? Стабильность, надежность и долговечность здесь важнее.

Линус вообще топит за чистый Си.

Ядро линукс- это 1) ядро операционной системы стационарной вычислительной машины 2) написана во времена, когда растов и го не было в помине 3) язык С никакой Раст не превзойдет по скорости 4) но С хреново подходит для современного скажем так корпоративного софта. Нет, не потому что он плохой, он как раз хороший, но стоимость разработки на нем - временная и финансовая- просто огромная, плюс хорошо писать на С надо учиться долго, программистов не наберёся

go появился в 2007-2009 году, хотя да, ядро было раньше.

Чистый си достаточно лаконичен и легко читается и пишется, особенно когда ООП в разумных пределах, но есть недостатки типа нет обработки исключений (так было лет 10 назад, когда папа, работая на французскую фирму, использовал си++ в режиме "си плюс пара плюшек", для OCR нужна была производительность и баланс по сложности и скорости). Тогда как "нативный" с++ это "неймспейсы классов неймспейсов", код просто чудовищно читаемый и неподдерживаемый, пример voip либа под телеграм. Пытался написать некую либу.. При этом в универе учили си 3 года, жаву год и с++ год, помимо всяких ассемблеров. Так вот, на си писать - требуется правильный склад ума, но читается он любым человеком, кто умеет в любой другой язык.

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

есть, но не настолько наркоманский. Повторю, libtgvoip или как её - её не то что писать, её даже читать невозможно, не сидя под чем-то тяжёлым

А что там не так?

Поддерживаю вопрос, куда смотреть? Посмотрел libtgvoip по-диагонали - это махровый C-с-классами, отягощённый многоплатформенностью (из-за этого везде пачки #if).

Вопрос уровня "как без автокадов и планшетов королёв человека в космос запустил или это ещё недостаточно сложный проект?"

больно и мучительно, долго и тяжело, и кстати в kernel с появлением c11 тоже встречаются дженерики

Спасибо за статью, интересное, особенно в части GC, теперь ещё больше хочется "потрогать" Rust. Но удивило следующее: `Go недостаёт: мощной поддержки IDE` (c). Typescript - это конечно, хорошо, но где поддержка TS лучше, чем go? VSCode? `Goland` от jetbrains просто "божественно" определяет все объявления, использование и имплементации, даже в сорсах, в отличии от `Webstorm` + TyepScript и других связок. Моё мнение, что данная характеристика напрямую зависит от выбранной IDE и косвенно от самого ЯП.

меня это тоже удивило в оригинальной статье, но я не имею такого опыта с TypeScript, чтобы оспорить этот момент ))

За Goland вроде как денег хотят. А дефолтный LSP у Go.... скажем так бесит больше, чем помогает. Он абсолютно не умеет работать с недописанным кодом, одна опечатка и все умные функции отключаются

Webstorm (ts) отвратительно работает с дженериками, а про более сложные вещи вроде ConstructorParameters молчу. Лично сделал 4 ишью, которые в работе уже как 2 месяца...

Да в vscode реально работает лучше, это скорее характеристика IDE

Я понимаю, что разговариваю с переводом, но автор бы хоть немного примеров вбросил что ли для сравнения, а не тоьтко ключевые слова.

Но вообще хороший такой наброс, нажористый. Я даже от себя добавлю

Скрытый текст
Клавиатура программиста на Go
Клавиатура программиста на Go

я ключевые слова не добавлял. всё переведено "один в один" с небольшими правками стилистики.

Это даже не перевод. Просто скопипастили в нейронку и ее выхлоп дальше скопипастили на хабр. Без всякой обработки

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

я это говорю вам как лингвист изучавший 5 иностранных языков, и сейчас изучающий 6й язык.

не надо проецировать свой личный опыт на других, пожалуйста!

А пунктуацию в этих пяти языках пока не изучали?)

Простите, не смог удержаться)

Пунктуация и переносы это маркер иноязычного автора, даже если всё остальное в тексте прекрасно.

видимо не изучал, так как не понимаю на какую проблему с пунктуацией вы намекаете ))

Если позволите.

Вам может показаться, что так и есть, (сложносочинённое предложение) но это полный перевод с построчной сверкой с оригиналом. Естественно, (вводное слово) нейросети помогают ускорить процесс перевода, который просто вручную занимает в 5 раз дольше.

Я это говорю вам как лингвист, (причастный оборот) изучавший 5 иностранных языков и (соединены союзом) сейчас изучающий 6-й (смешанный способ оформления числительных) язык.

Видимо, (вводное слово) не изучал, (обособление придаточного изъяснительного) так как не понимаю, на какую проблему с пунктуацией вы намекаете.

да, верно, у меня в школе была по русскому тройка, а по иностранным и математике пятерки ))

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

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

Моё использование русского составляет 0-5% в обычный день на протяжении многих лет. Не надо сравнивать это со своим опытом.

Тогда к чему апелляция про тройку в школе?

К тому что многие правила русского я не выучил со школы. А так как мой основной язык не русский сейчас, то в моём русском может преобладать логика моего основного языка - английского. Несмотря на то, что я даже очень стараюсь писать по-русски хорошо. ))

Нейронка так не переведёт. Текст немного лучше чистого джипити.

Rust вместо этого пишет лишь оператор '?'

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

Вот это вообще шлак полный, конечно
Вот это вообще шлак полный, конечно

конкретно написано, что это перевод статьи!

эти ключевые слова присутствуют в оригинальной статье. я думал удалить сначала, но передумал...

Не понял, вы через ллм прогнали выхлоп другой ллм? А в чем ценность статьи тогда?

ценность статьи только лишь в ее содержании. ллм помогает, но не заменяет
"трудности перевода".

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

У меня вообще ощущение, что на хабре живые люди уже не пишут.

Вы правы! Иногда действительно кажется, что статьи и комментарии пишут роботы или нейросети — настолько всё стало шаблонным и безликим. Но живые люди ещё есть! Просто многие, наверное, устали от токсичности или переключились в режим «читаю, но не комментирую». Лично я вот стараюсь писать по-человечески — может, если таких станет больше, атмосфера снова изменится в лучшую сторону. 😊 А вам как кажется — что могло бы вернуть Хабре «живое» общение?

Это написано ллмкой :)

и зачем вам тратить время на эти комментарии не посмотрев оригинал?

... паузы GC неприемлемы. Именно поэтому крупные компании всё чаще выбирают Rust (или даже C++) в этих средах

А что, когда-то было иначе? Где-то, где важен каждый такт, были языки с ГЦ? По личному опыту, там всегда сидели плюсы, которые сейчас вытесняются растом.

Ну а Го осел в нишах, где нужна параллельность-конкуррентность

Не, ладно, дженерики, но когда я узнал, что в Go надо после каждой строчки кода проверять err != null - это ж застрелиться можно

Гораздо веселее читать явовские стек трейсы на три экрана, правда ведь?

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

Их читать 5 минут. Мало того, хорошо бы иметь автотесты, чтобы читать реже пришлось, это не зависимо от используемого языка.

А вот размазать 100500 проверок ошибки на null по всему крупному проекту, как масло на хлеб - это уйма времени и неиллюзорный шанс где-нибудь забыть это сделать.

Централизованного перехвата ошибки я так понял нет. Но при этом с Яве / C#, если есть острая необходимость поманьячить - можно сделать как в Go.

Ну вообще есть, просто в Go нужно иметь понимание ошибок, которые нужно именно обработать и которые должны прервать выполнение(panic). Если очень надо именно выбросить ошибку вверх по стеку, паникуйте и отлавливайте ее централизовано

Джавовые стектрейсы ванлав. По ним можно понять про место ошибки все. И кто кинул и кто вызвал и что между ними было. Дебаг становится заметно проще.

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

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

Как контекст ошибки по трейсу понимать будете?

добавляем необходимые поля в кастомный класс исключения

Ну т.е. колл-стеков для нормальной диагностики ошибок не достаточно и придется вокруг вызываемого метода писать try-catch чтобы заврапить ошибку в кастомный класс исключения. Чем это лучше кода типа?

result, err := geocodingClient.GetPosition(cityName)
if err != nil {
	return nil, fmt.Errorf("get position '%s': %w", cityName, err)
}

На практике, я думаю, враппинг всего в try-catch довольно утомителен и вы просто его не делаете, а восстановление контекста базируется на надежде что что-то полезное будет в соседних записях логов или в текущем span если есть structured logging. Ну или будет "фиг его знает, почему тут вылетел InsufficientPermissionsException, придется дебажить".

Кастомный тип ошибок(ака исключение нужно типа) удобен хотя бы тем что его можно сматчить, там где это необходимо. Например в тестах.

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

Такую конструкцию как вы указали, проверять в тестах сомнительно, ибо можно проверить только по тексту.

errors.As

errors.Is

Я об этом написал в своем комментарии

Суть в том что при таком подходе, а он как по мне верный, отличный от отдельного класса исключения нет.

В приведенном же коде, с fmt.Errorf, проверить можно только ту ошибку что вернётся из GetPosition

Прочитал ваш комментарий не внимательно. Действительно, проверить ошибку обернутую с помощью fmt.Errorf нельзя.
Она годится для для быстрого расширения контекста там, где нам не надо проверять типы. В большинстве случаев этого более чем достаточно.

В иных случаях нужно что-то типа:

type gError struct {
	err  error
	code codes.Code
}

func (e gError) Error() string {
	return e.err.Error()
}

func (e gError) GRPCStatus() *status.Status {
	return status.New(e.code, e.err.Error())
}

func (e gError) Unwrap() error {
	return e.err
}

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

Можно подумать, с Go-шных return nil, err будет больше информации.
Получение нормального контекста ошибок всегда требует определенной работы.
Что в Golang, что в Java, что в Rust-е.

Но факт в том, что с Golang практически каждая строчка кода сопровождается проверкой err != nil. И это бесит.
В Java с try-catch все-таки кода меньше на выходе. Даже если это просто проброс ошибки дальше, а не вдумчивая обработка.
В Rust с его Result вообще отдельно от метода можно преобразование ошибок сделать - чисто на описании типа и его конвертациях. Сам метод еще чище будет. Но читаемость страдает, на мой взгляд.

Можно подумать, с Go-шных return nil, err будет больше информации.

Так не пишит так - https://github.com/uber-go/guide/blob/master/style.md#handle-errors-once

Golang практически каждая строчка кода сопровождается проверкой err != nil. И это бесит. В Java с try-catch все-таки кода меньше на выходе

Ну т.е. с го приходится думать что ты пишешь и это бесит. Понимаю.

В Rust с его Result вообще отдельно от метода можно преобразование ошибок сделать - чисто на описании типа и его конвертациях

Можно, только на практике 99% проектов будут через anyhow&thiserror и для нормальной диагностики надо будет добавлять with_context(|| ...) на вызовы с Result.

Типичная обработка ошибки - залогировали ошибку, откатили транзакцию, работаем дальше.

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

Если же каждый чих проверять - то это называется не "приходится думать", а "заниматься ерундой микроменеджментом". Высокоуровневые языки нужны для упрощения рутины.

Если так хочется думать и контролировать каждый чих - можно и к assembler-у вернуться. Контроль всего и вся на 100%.

Ну т.е. колл-стеков для нормальной диагностики ошибок не достаточно

практически всегда достаточно

и придется

практически никогда не придется

Тут не нужно теоретизировать, нужно открыть любой реальный проект на джаве и посмотреть, пишутся там try-catch вокруг каждого вызываемого метода или нет)

практически всегда достаточно

Все так, и tracing со span'ми был добавлен в spring именно потому что колл-стеков практически всегда достаточно для диагностики.

ниче не понял, какая связь вообще) скажите, вы реально пишете на джаве и испытываете трудности, или просто где-то что-то слышали?

ниче не понял, какая связь вообще)

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

скажите, вы реально пишете на джаве и испытываете трудности, или просто где-то что-то слышали?

Я не испытываю трудностей потому что уже много лет не пишу на джаве. А вы пишете на го или "просто слышали"?

Какое отношение распределённые системы имеют к способу обработки ошибок? Распределённость накладывает свои проблемы поверх любого подхода.

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

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

Так имба же! Меньше чем через год разработки на Java, появляется навык выделять ключевое достаточно быстро (а может дело в том, что IntelliJ Idea подсвечивает синим то, что относится к коду приложения, и явно ненужные вещи сворачивает(omit)), к тому же если все сложно, то можно весь стектрейс просмотреть, чтобы восстановить картину. В Java с концепцией проверяемых исключений всё неоднозначно, но и это поправимо со SneakyThrows

В Java с концепцией проверяемых исключений всё неоднозначно

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

Пишешь функцию must(<твоя функция>)

интересно однако

Все вот говорят, что им не нравится err != null, а покажите пожалуйста, языки в которых архитектурно нет необходимости проверки возвращаемых исключений с возможностью продолжения работы с учётом невалидных данных в переменных? Или большинство ловит краши и считает это нормальным?

Я думаю, никто не говорит, что не надо проверять ошибки. Просто (условно), в Go нужно перепроверять ошибку после каждого шага, потому что если вызываемая функция вернула ошибку, а следующая за неё завершилась корректно - err станет nil. Переодически ловлю такие случаи. В других же языках можно было бы бросить/поймать исключение уровнем выше, если хотя бы один вызов завершился некорректно.

И к чему это приводит?
Я имею в виду вот это самое: "бросить/поймать исключение уровнем выше".

Сам видел когда ловят в main, а дальше все без обработки хоть единой возможной ошибки 100500 строк кода. И когда там ловится то потом замаешься пониами что пошло не так.

Ну блин, тут классическое "заставь дурака молиться". Понятно, что не стоит оборачивать всю программу в try-catch, но если я делаю что-нибудь большое с сетью, но в рамках одной операции (допустим, в цикле скачиваю файлы), мне гораздо проще поймать TimeoutException один на всю функцию загрузки, чем после каждого файла в теле цикла проверять "а не было ли тут таймаута?". И это первое что в голову пришло, таких кейсов - море

Да я ни разу и не спорю. Использование с умом и по месту любой механизм - рабочий. Но есть тонкая разница между "можно так, а можно на потом", и когда тебя, довольно грубо (не спорю), но сразу заставляют подумать "а что если?".

Причем в разработке объемного решения никто не мешает в первой версии просто написать: if err != nil { panic(err) } в месте где "ну вот сейчас я не хочу думать об этом, подумаю после того, как допишу основную логику". А вот когда оно паникнет (а это случится как правило еще до прода) тогда уже подумать, а как же это нужно обработать.

Кто же потом такое переписывает? Работает - не трогай. Вот и оказываются большие проекты с непойми как и где разбросанной логикой обработки исключений среди бизнес логики. И это не программисты плохие это язык плохой.

включаете рул на линтере, получаете список ошибок по использованию panic(err) и исправляете.

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

Вникать в контекст нет ни времени ни смысла.

Тяжело вам приходится.

Не обманывайте сами себя. Никто никогда не тратит время и не думает над задачами которые уже работают в проде и не доставляют проблем. Объяснить их ценность бизнесу невозможно.

Вы берёте экстремальный пример. Например, часто есть сгруппированные по смыслу операции, которые можно обработать вместе.

Напр. я читаю записи из БД, и если они проваливаются на одном из шагов, то в Питоне я проброшу исключение наверх и сделаю центральный обработчик для этой группы через try/except, а в Go мне приходится делать обработку на месте для каждой возможной ошибки, и все они будут просто возвращать nil,err , из-за чего только кода с возвращением ошибки на экране становится больше, чем полезной нагрузки, и потом ещё поди разбери, что откуда вернулось.

все они будут просто возвращать nil,err

Не будут они возращать nil,err, это буквально задокументированный антипаттерн, который автоматически обнаруживается линтерами. Если у вас есть разные шаги чтения, то они логически имеют разный контекст и должны иметь разные ошибки. Например, если я считаю поле из рекорда в базе и оно оказалось строкой, хотя ожидалось число, то ошибка должна содержать имя колонки, ожидаемый тип, существуй тип и описание какой запрос был выполнен, а не просто InvalidCastException, который перехватывается на уровень стэка выше и дальше гадай что и где пошло не так.

Ну себя хотя бы не обманывайте, не напишете вы руками нормального уникального сообщения об ошибке для каждого загружаемого из базы поля. А InvalidCastException при наличии отладочных символов хотя бы номер строки покажет.

data, err := readInt(columnName)

	if err != nil {
		if errors.Is(err, db.ErrInvalidType) {
			return nil, fmt.Errorf("read column '%s' as int: %w", columnName, err)
		}
		return nil, fmt.Errorf("read column '%s': %w", columnName, err)
	}

И так 42 раза. Для всех колонок. И кому оно надо?

если вы читаете 42 колонки в ручную, а не обощенным кодом, то у вас проблемы в коде посерьезней чем бойлерплейт обработки ошибок.

Мапперами читаю обычно. Там буквально для каждой колонки строчка ее читающая и кладущая в переменную. Просто, понятно, безопасно и поддерживаемо.

У нас в компании вроде довольно строгие линтеры, но они на такое не ругаются. И нам, в целом, не нужна вся эта тягомотина с типами ошибок и т.д., потому что обрабатываются они в бекэнде одинаково, поэтому мы пользуемся более простым алгоритмом - добавляем какой-то описательный текст и выбрасываем ошибку в ответе сервера. Этого УЖЕ достаточно чтобы понять, какая ошибка и где произошла, однако, если посмотреть на одну из функций, то там одних if err != nil {return fmt.Errorf(...)} получается 20 строк в функции на 65 строк в сумме (один из примеров). Если много вызовов в сторонние API, то порой больше половины строк - возврат разнообразных ошибок.

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

Вы сами пишите "добавляем какой-то описательный текст", "{return fmt.Errorf(. ". Как это противоречит "return nil,err это антипаттерн"? Я же не говорю о типизированных ошибках, я говорю о добавлении контекста.

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

Таких или подобных ситуаций очень много, и какой-нибудь классический try/except как в Питоне гораздо удобнее, когда обработку исключений можно централизовать, и не быть вынужденным размазывать обработку ошибок для КАЖДОГО вызова функции.

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

В других языках есть более удобные, гибкие и - главное - композируемые способы решать эту проблему

в Go должны однажды решить эту проблему...

я вижу периодически делают предложения, но они не проходят.

вот например интересный пакет errless: https://github.com/mfatihercik/errless

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

этот пакет errless не пример красивого решения проблемы перехвата ошибок в Go, а всего лишь чья-то креативная попытка реализовать подобие того, что в других языках лежит в основе ))

Это понятно, но все же есть кейс с преобразованием строки к int и обратно. Как решается этот кейс без явного отлавливания ошибок в других языках?

https://doc.rust-lang.org/std/result/
https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-result/
https://www.scala-lang.org/api/3.x/scala/util/Either.html
https://hackage.haskell.org/package/nri-prelude-0.6.0.6/docs/Result.html

обычно совместно с подобным механизмом идёт запрет бросать исключения где попало (в той или иной форме)

пример для Rust

let string_value = "123";
let conversion_result = i32::try_from(string_value.parse::<i64>().unwrap());
    
if let Ok(number) = conversion_result {
    println!("Number: {}", number);
} else {
    println!("Failed to convert");
}

Kotlin

try {
    val stringValue = "123"
    val number = stringValue.toInt()
    println("Successfully converted to: $number")
} catch (e: NumberFormatException) {
    println("Conversion error: ${e.message}")
}

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

На rust я не вижу принципиального отличия от конструкции на go:

С телефона блок кода не уставился

num, err := strconv.Atoi(str)
	if err != nil {
		fmt.Printf("Ошибка преобразования строки в число: %v\n", err)
		return
	} else {
	fmt.Printf("Успешно преобразовано: %d\n", num)
}

Можно даже сделать подобие через inline if

На rust я не вижу принципиального отличия от конструкции на go

Принципиальное отличие кода выше на Rust в том, что Rust гарантирует валидное значение переменной number в любом месте скоупа (при условии отсутствия unsafe блоков). Вызовом unwrap() разработчик явно подписывается, что при провале конвертации должна вызваться panic() и поток исполнения дальше не пойдёт.

Go же разрешит написать это ваше num, err := strconv.Atoi(str) и затем вместо условной обработки ошибки просто прибавить что-то к num без проверки err. Этот код свалится только во время выполнения.

PS: зачем две конвертации подряд, сначала i32 потом i64?? Этот код не эквивалентен коду на Go.

если мы знаем тип отлавливаемой ошибки

мы всегда его знаем - это Exception) Если серьезно, ситуации когда нужно в коде программы предпринимать какие-то действия по исправлению ошибки исчезающе редки, обычно либо нужно чтобы код не кидал ошибок вообще, либо плевать что он там кидает, всё равно чинить это потом ручками. То есть от эксепшена нужно две вещи:

  1. чтобы он содержал достаточно контекста для понимания произошедшего

  2. чтобы он не останавливал тот код, который не должен останавливаться

Никто не пишет на каждый чих по try-catch, они пишутся только там, где никакие ошибки не должны пролезть выше по стеку (ну или где хочется сделать жизнь юзера чуть проще и добавить больше контекста к произошедшему)

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

Посмотрите как другие языки позволяют это делать элегантно: https://elixirschool.com/ru/lessons/basics/control_structures#with-3

Go просто отстаёт на многие годы от удобных ЯП, это факт.

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

вот такой вариант я использую в одном пакете где возможна паника.

func reflectCall(fn reflect.Value, params []reflect.Value) (result []reflect.Value, err error) {
	defer func() {
		if r := recover(); r != nil {
			// Convert the recovered panic to an error
			switch x := r.(type) {
			case string:
				err = fmt.Errorf("%s", x)
			case error:
				err = fmt.Errorf("%w", x)
			default:
				err = fmt.Errorf("%v", r)
			}
			log.Printf("Panic occurred: %v\n", r)
			log.Printf("Stack trace:\n%s\n", debug.Stack())
		}
	}()
	return fn.Call(params), err
}

в итоге пользователь получает ошибку, а в лог пишется ошибка и стек трэйс.

почти как try catch ))

Я вот сейчас пальцем в небо тыкну и на первом же блоке с err != nil нам попадется

		if err != nil {
			return nil, err
		}

Проблема в том, что ошибки то не проверяются, а просто кидаются выше по дереву вызовов до места вызова. Из-за чего разработчики должны писать лишний бойлерплейт.
В Расте вот немного умнее подошли к обработке ошибок. Функция возвращает Enum, который может содержать ошибку или значение и ее можно распаковать оператором ?. Если имеем ошибку возвращаем ошибку, если нет, получаем значение.

fn check_even(num: i32) -> Result<i32, String> {
    if num % 2 == 0 {
        Ok(num)
    } else {
        Err(format!("Число {} нечетное", num))
    }
}

fn process_data(n: i32) -> Result<i32, String> {
    let val = check_even(n)?; // Распаковка через ?
    println!("Обработка значения: {}", val);
    Ok(val * 2)
}

fn main() {
    match process_data(4) {
        Ok(res) => println!("Результат: {}", res),
        Err(e) => println!("Ошибка: {}", e),
    }
    
    // Для нечетного числа
    match process_data(5) {
        Ok(res) => println!("Результат: {}", res),
        Err(e) => println!("Ошибка: {}", e),
    }
}

В Zig тоже достаточно похожая и органичная обработка ошибок, только там error union вместо Result и try вместо ? оператора.
Но авторы Го на любое предложение с мыслями о эволюции языка просто зыкрывают тему со словами "У нас все хорошо, ничего нам не надо". Я до сих пор не понимаю, каким чудом удалось в Го протолкнуть обобщения.

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

даже формат презентаций на GopherCon в этом году меняется. каждая презентация будет не более 30 минут и без времени на вопросы-ответы в конце. а всё потому что старикам уже в тягость всё это...

а всё потому что старикам уже в тягость всё это

Это либо неверно, либо дела совсем плохи - презентации делают одни старики.

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

В смысле логики применение которой показалось забавным.

Если участвуют не только старики, то объяснение изменений усталостью стариков не работает и надо искать другие или, как минимум, дополнительные причины.

Значит, если объяснение правильное и работает, то в презентациях участвуют только старики.

Обратите внимание - логика основывается на, гм, логике и утверждениях, а не на том что где как на самом деле.

А что где как - надо будет посмотреть на конференцию. Ограничение в 30 минут - no issue ибо 1 презентация на 6 часов == 18 презентаций по 20 минут. Отсутствие времени на вопросы - (большой) минус если это всё, и плюс если вопросы и ответы возможны в иной форме. А в программе и Community Day и много чего ещё, что можно провести хорошо, а можно и отнюдь.

За десятилетие в этом году впервые меняется формат презентаций на GopherCon - не более 30 минут и без вопросов-ответов. Раньше было 2 формата: 45 минут и 30 минут, и были вопросы-ответы после презентации.

Недавно в 2024 году из руководства разработки Go ушел Russ Cox, а никто новый не пришел. Просто повысили тех кто уже был в команде. Кокс устал и ушел, а остальные - тоже люди. Такая у меня логика

Ну, формат презентаций может меняется и к лучшему. Было - имел вопрос и не успел задать, стало, если действительно к лучшему - пришлось вопрос запомнить, но на другой встрече точно задал,

Если Russ устал - отлично, но что-то мне вспоминается как о команды Python и Flutter в Гугол тоже ноги вытерли. В разработку языка брать на высокую должность со стороны - это опасно, так что всё не так печально, а просто печально.

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

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

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

Error.Is Error.As вам в помощь.

Проблема в том, что нужно писать чёртов бойлерплейт, если обрабатывать не нужно, а нужно протащить куда-то наверх. И писать эти проверки на каждом уровне по всему коду. Код просто замусоривается. В Rust тоже нет исключений, но то же самое по сути делается одним символом ?. Почему в Go так же сделать нельзя? Что принципиально мешает?

Из-за этого не люблю писать на Go и когда читаю исходники чего-нибудь, меня просто корёжит от этих бесконечных проверок на nil. Я терпеть не могу бойлерплейт, и это задевает моё чувство прекрасного. Я не понимаю как это может устраивать, для современного языка, у которого не было груза обратной совместимости можно было подумать и сделать нормально изначально. Ну или хотя бы не отклонять так ревностно любые предложения на эту тему, а запланировать что-то с этим сделать хотя бы в версии 2.

Почему в Go так же сделать нельзя? Что принципиально мешает?

Авторы языка мешают. Они специально делали язык таким. В итоге есть даже шутка что вместо сахара в golang положили синтаксическую соль. В целом если посмотреть дискуссии там тяжело шла тема давайте добавим генерики. Причины просты. Люди начнут использовать генерики там где их не надо. Но с другой стороны терпеть интерфейс ехал через интерфейс тоже не очень приятно.

Из-за этого не люблю писать на Go и когда читаю исходники чего-нибудь, меня просто корёжит от этих бесконечных проверок на nil. Я терпеть не могу бойлерплейт, и это задевает моё чувство прекрасного.

А вот в golang это скорее норма. Более того библиотеке языка есть штатный парсер сборщик генератор кода на go. По этому где проблема решается тем что в язык добавляют конструкции в golang говорят сделайте генератор кода. Из-за простоты самого языка это довольно легко делается.

В целом меня например в других языках напрягает то что местами люди слишком увлекаются синтаксическим сахаром и не добавляют то что действительно надо. В качестве примера можно взять dart. Я его пробовал во flutter. И там вот слишком много вещей засахарено без какой либо пользы. Просто потому что можем ну и так же короче писать. В итоге одно и тоже можно написать двумя тремя разными способами и это тоже не очень хорошо смотрится.

Тут скорее должен быть вопрос к написавшему: а почему бы ошибку не обработать на месте или не добавить ей контекста?

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

В теории да, удобно, можно не обрабатывать не обязательные или маловероятные ошибки, меньше кода.

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

Скрытый текст

Человеческий фактор вообще неприятная штука. На рынке достаточно много разработчиков, которые не будут делать не обязательные вещи, даже если их об этом прямо попросить. Лично сталкивался с такими: иногда нужно 2-3 замечания, прежде чем до человека дойдет, что так писать не стоит, что это вызывает гнев у коллег. И есть некоторые уникумы, которые привыкли писать в своем стиле, и чужое мнение им вообще не аргумент, но таких к счастью совсем немного. И со всеми из них приходится, так или иначе, через их код, иметь дело. Особая когорта разработчиков, т.н. летуны: кода человек приходит на проект, пишет ужасный код, а потом увольняется, а ты через несколько лет огребаешь последствия за него, и тебе приходится все это переписывать по-человечески, потому что возникла потребность внести изменения именно в этот функционал. Почему такое вообще возможно? Потому что такие проекты фактически не имеют владельца, кодом никто не владеет, нет ни правил, ни надзора, заказчик понятия не имеет как управлять кодом и что там вообще есть, ему просто нужно исправить или изменить функционал готового кода, и он даже согласен если конкретно ты все приведешь в порядок, но бюджетов на значительные изменения в коде просто нет, и ты либо 80-90% работы сверх задачи делаешь бесплатно, либо делаешь только конкретно тот объем работ, который тебе оплатили.

Поэтому на практике это иногда вызывает боль.

Также исключения - это часть неявного поведения, магии. А магия тоже иногда выстреливает и причиняет боль: ищи потом, кто и где изменил поведение кода, где эта магия спрятана, ведь явных связей в коде для магии просто нет.

Думаю именно поэтому авторы go и заложили такие строгие ограничения в свое детище: просто устали от проделок менее разумных коллег, и устали от магии.

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

С явными контрактами всегда можно ткнуть на явную связь и пройтись по цепочке таких связей до источника проблемы. Даже без умных анализаторов IDE. Но явные связи упрощают работу и IDE: в других языках магия иногда просто не поддается автоматическому анализу, IDE не подсвечивают проблемы с ней, не видят неявные связи.

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

Меньше логики: проще писать, проще читать, проще понимать, проще дебажить, проще расширять (меньше - это разумеется без фанатизма).

Не понимаю про магию, можете детальней раскрыть мысль?

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

Я не очень много писал на go. Но всю дорогу так и не смог привыкнуть к обязательному пробросу ошибок. Как и не смог найти минус в отсутствии такой обязательной необходимости в PHP. Хотя 2 года писал параллельно на обоих.

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

Нет, никто не говорит, что структурный подход (с try/catch) единственно правильный.

Просто обычно в языках сильно больше возможностей работы с чем либо (н.р. разные типы циклов, разные возможности обработки ошибок и т.д.).

Ибо для решения разных проблем нужны разные подходы. Серебряной пули, какгрица, не существует.

НЛО прилетело и опубликовало эту надпись здесь

в f#? try/with там нет?

честно я не сильно шарю за этот язык, но гугл говорит, что не только result.

Всякие `?` в rust позволяют же пробросить ошибку дальше? (тож в расте не силен, но первое что нагуглилось).

А в go только портянка из if'ов.

да, но мы рассматриваем не средний индекс на рынке, а тихий сдвиг в особо крупных проектах

А откуда дровишки?
Можете своих циферок подкинуть подтверждающих этот сдвиг?

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

я поделился переводом только потому, что мне эта тема близка и интересна.

Автор оригинала - не американский разработчик, а индийский копирайтер который с нейросеткой "пишет" по 15 статей в день, а вы зачем-то это нейроговно несете на хабр.
Вот здесь этот клоун признается что он даже не программист
https://medium.com/@akshatkapil2249/this-one-chatgpt-prompt-made-me-5-000-no-coding-required-b03b08b7e387

какие 15 статей в день, когда у автора всего их около 15? ))
вы читали вообще другие статьи, чтобы делать вывод на основании одной статьи, написанной для "пиара"?

Вы ошиблись всего на порядок, у автора 118 статей. При этом он дорвался до llm-бредогенератора всего лишь 9 апреля, то ли еще будет! Другие статьи "автора" (как и эту) я, конечно же, не читал, у меня еще с середины 2023 года выработался иммунитет к medium и нейроиндусам, которые заполонили эту площадку и окончательно испортили.

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

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

я проверил и оказалось 116 - это 117 минус первая (последняя в списке) пустышка

Это прям в корне всё изменило (нет).

Да, медиум конечно скатился (по крайней мере в области айти) в самое днище. Сейчас в рассылке если вижу автора индуса - даже не читаю ничего. По заголовкам тоже можно определить шлак, типа "Вы всю жизнь использовали принт не правильно...". Но все же редко-редко, но бывают стоящие статьи.

10 лет назад я работал в команде, где был главный тестировщик - индус. И он был самый неопытный тестировщик из всех что я знал. Я бы сказал, что он был позором всех индусов, настолько он мало понимал в тестировании. Но в этой компании всё руководство было прогнившим.

10 лет спустя, мой опыт работы с индусами сильно изменился. в среднем 7-8 индусов из 10 реально хорошо разбираются в своей теме.

А вы посмотрите на руководителей (CEO, CTO) в Big Tech (и не только) - индус на индусе:

  • Microsoft (Satya Nadella)

  • Google (Sundar Pichai)

  • Adobe (Shantanu Narayen)

  • IBM (Arvind Krishna)

  • Youtube (Neal Mohan)

  • World Bank (Ajay Banga)

  • Starbucks (Laxman Narasimhan)

  • и так далее...

Да, они все - индусы...

Я лично не фанат индусов, но если посмотреть вокруг, то ситуация меняется и это надо признать.

Каминг-аут, однако! 8-)

откуда американский автор оригинала взял данные я не уточнял. но формат мне понравился и я даже сам

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

В особо крупных проектах Go и так не использовался часто

А он на это и не рассчитан. Его ниша - cli-утилиты, мелкие сервера и микросервисы. Что-то большое на нем писать - это страшно даже представить, какая боль это будет. Но крупные проекты редко представляют из себя огромный монолит. Обычно это взаимосвязанный набор сервисов, вспомогательных инструментов, и инфраструктуры, целый зоопарк языков и множество команд разработчиков.

cockroachdb для вас достаточно крупный проект? kubernetes? grafana? terraform?

Tiobe index апрель 2025

  1. Visual Basic +1.24%

  2. Delphi/Object Pascal +1.06%

  3. Fortran +0.57%

очень, очень хороший источник

Пробежал текст статьи "по диагонали" (это важно) - и вижу тут не столько про Go, сколько НЛП-шку для программистов на тему "Rust лучше по-любому" ))

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

Взгляд со стороны..

Go: мы написали на го Docker, Terraform, Kubernetes

Rust: вот вам на расте новый cat, новый grep, ls и новый top с цветами и колокольчиками!

да, оно-то так и есть если посмотреть со стороны. но со стороны не всем видно, что происходит в Big Tech, о котором идет речь.

Так а примеры то будут? Я вижу что это перевод, но вы его так активно защищаете что хочется попросить примеры.

эти примеры заслуживают внимания!

Любая большая вещь, превращаясь в индустрию, начинает жить своей жизнью. Уже неважно для чего она была - важна жизнь внутри.

Джуны растут до синьоров, внедряются внедрения, идёт процесс ради процесса и бег ради бега.

Придумаем 100500 новых языков с перламутровыми пуговицами, перепишем старое, потом перепишем ещё раз, потому что у самурая нет цели, есть только Путь.

Пока есть те, кто готов инвестировать в ожидание выгоды.

Просто разница подходов -- пока одни скачут по верхам (тоже полезным), другие пишут фундамент.

ну почему, есть и аналог elasticsearch и другие вещи, например неделю назад в новостях был arroyo, как я понимаю это аналог apache flink. Вообще-то есть еще и firefox с которого я прямо сейчас пишу. Не адвокат rust, более того меня больше напрягают эти приписки "сделано на расте" потому что идет какое-то навязывание, что после этого софт почему-то сразу будет работать со сверхсветовой скоростью. Я думаю надо дать еще время, код на расте ж вроде пишется не так быстро как на go или java :)

Какой-то пиар Rust.

может надо добавить подзаголовок "Это не пиар Rust"? ))

Лучше ключевые слова такие добавить )))

Кажется, будто всё это написала большая языковая модель. Может, стоило бы просто включить в статью запрос «промт», а каждый из нас мог бы использовать свою любимую модель для создания собственного варианта статьи?

Заключительные мысли: Go не умер — но его время на вершине может закончиться

Не в упрёк или попытаться что-то оспорить, просто ради интереса: а что это за вершина?

Все бегут на раст: Это же С++, но лучше!!!

А, потом все побегут на аналог PHP: На нем быстрее чем на расте!

А, потом...

аналог PHP

Дык это ж node.js, и на него все уже убежали. Но таки да, не быстрее раста))

Мне кажется PHP менее требователен к ресурсам, чем нода.

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

Так я не понял, Big Tech уходит от Go, или это домыслы автора исходя из минусов языка?

Прочитал оригинал статьи и комментарии к ней. В них народ хором пишет, что статья ни о чём, без ссылок, фактов и подтверждений. Голословненько!
Непонятно, зачем её было переводить...

Зачем переводить статью какого-то индуса, который холиварит на тему "Rust круто, давайте всё на Rust перепишем, а язык {подставьте любой} уже устарел, его на помойку". На Rust-е за 12 лет существования ржавого на нем написаны буквально единицы крупных проектов, типа Fuchsia OS и часть Firefox(может ещё есть удачные примеры, но их надо специально выискивать), когда как на любом другом по 5-10 пишут каждый код.

Rust идеально подходит как нишевый язык, на котором можно писать отдельные компоненты/плагины/сервисы, где критична не скорость( по ней он тем же плюсам проигрывает), а безопасная работа с памятью. А всё остальное можно писать на чем-то нормальном, что знает больше людей при одинаковом уровне удобства и не морочить голову с поддержкой, поиском и заменой кадров, обучением новичков и т.д.

Даже в подборке работы от Хабра очевидно, какой перекос и что если за десяток лет он не исправился - не исправится и дальше

Надо учесть, что русскоязычный Big Tech и западный отличаются довольно сильно. Если там идет тихий переход с одного к другому, то это не значит, что тут это станет сразу заметно и ощутимо.

Если в Cloudflare или Dropbox переписали внутренние платформы на Rust, то это вообще никак не отразится на рынке.

А тут речь идет именно об изменениях внутри крупных компаний.

Мне кажется с языками программирования все немного сложнее чем описано в статье: не может просто большая компания взять, отказаться от одного языка (на котором написано куча отлаженного бэкэнд софта) и начать внедрять другой язык. Нужно чтобы либо сотрудники компании освоили новый стек - либо где-то взять новых сотрудников на новый язык.
Go на мой взгляд - изначально был инструментом оптимизации, который не имеет ООП, но зато удобнее в работе с многопоточностью чем Си.
И если что-то уже оптимизировано на Go - то зачем это вдруг переделывать на Rust или Kotlin?
Я чуть чуть работал с Go и с Rust - и конечно Rust ощущается удобнее и веселее в разработке - но мне кажется странным, что если биг тех освоил Go - он возьмет и сразу будет переделывать это на Rust? Как будто в мире полно рыбы - и если что-то нужно оптимизировать - то это действительно какой-нибудь старый бэкенд на интерпретируемом языке (или даже бывает новый бэкенд на питоне пишут, потом переписывают на что-то побыстрее) - и тут любые быстрые языки хорошо - и компании будут выбирать исходя из возможностей своих специалистов.
Или я не правильно понимаю как дела делаются в бигтехе?

Go когда-то доминировал в инструментах для серверной части, CLI и DevOps.

А когда это было? Я все проспал?

Docker, Terraform, Prometheus, Grafana и так далее

Статья написана в вакууме.

Например, по поводу ошибок. В наше время даже самый тупенький ИИ дополняет if err != nil раньше, чем вы подумаете о том, что вам надо обработать ошибку.

А ведь рефакторинг и поддержка в крупных организациях гораздо более важны, чем собственно написание самого когда.

if err != nil гораздо проще для мозга, чем дополнительные сущности, как в rust, zig и (плюёт три раза через плечо) Java. В результате понимание простого Go кода происходит быстрее. Именно тут и появляется экономия времени. Эти минус доли секунд восприятия в конце рабочего дня складываются в меньшую усталость и большее удовольствие от работы.

Typescript и Rust крайне легко позволяют программисту заниматься "сублимацией" над типами и прочими хитрыми конструкциями языка. В результате никто не понимает, как этот код на самом деле работает. Даже его писатель забудет об этом. Go просто не даёт возможности написать переусложненный код. И в результате его рефакторинг гораздо проще даже для новых людей.

То, что крупные корпорации увеличивают использование Rust говорит только о том, что им в определенных местах нужно то, чего Go не даёт: это как раз наличие сборщика мусора, который, к сожалению, даёт непредсказуемые задержки, и, конечно же, Rust более производителен в супер-интенсивных частях инфраструктуры. Раньше они эти части тупо писали на C.

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

Да, Golang прост для чтения и понимания. Но это не мешает мне считать не самым удачным решением бесконечные err != nil в коде. Но да, это просто для чтения, спору нет.

И да, Rust сложен для чтения. Не понимаю, причем тут TypeScript - это C#/Java только чуть сбоку. Мне вообще показалось, что TypeScript упоминается как средство запуска WebAssembly-модуля, написанного на Rust )

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

Go просто не даёт возможности написать переусложненный код.

В Go есть if, else, for, nil, указатели, есть даже рефлексия. Что вообще мешает с помощью этого написать код любой переусложненности? Или по вашей логике на C просто невозможно написать переусложненный код? Или если взять Java 5 версии где в основном были if да for, то там весь код был куда комфортное и читабельнее а разработчики продуктивнее? Не хочу расстраивает но я видел проекты на java 5.

то, чего Go не даёт: это как раз наличие сборщика мусора, который, к сожалению, даёт непредсказуемые задержки

А в чем проблема не использовать сборщик мусора на Go когда это требуется?

Язык активно "мешает" писать сложный код. Он "сопротивляется" этому. А так как хороший программист должен быть ленивым (больше думать, чем плевать кодом), то, используя Go, мы код меньше переусложняем.

Если отключить в Go сборщик мусора, то уже лучше на C писать. Головная боль с памятью будет такой же, но и скорость работы будет выше. В этом конкретном случае Rust - идеальное решение.

Язык активно "мешает" писать сложный код. Он "сопротивляется" этому. 

Может всё-таки расскажете как он это делает вместо того чтобы повторять эту мантру?

Если отключить в Go сборщик мусора, то уже лучше на C писать.

Вы когда-нибудь игры писали?

  • Как мешает? Очень просто мешает. Мало ключевых слов, простейшая по сравнению с Rust и Typescript система типов, даже дженерики урезанные. И т.д. Вы, конечно, можете писать переусложненный код, кто-ж вам запретит. Но это будет сложнее, чем писать простой код.

  • Зачем писать игры на Go? Это странно... Язык - это инструмент, а инструмент надо выбирать под задачу. По этой же причине Rust не станет лидером среди игровых языков. Потому что AAA игры на Rust будут выходить раз в 50 лет)

К сожалению, такое упрощение приводит к копипасте (той же обработки ошибок например) и типичным для копипасте ошибкам - см блог пвс-студии. Но в общем, ничего особо ужасного.

Тут пробегала целая статья, почему игры на расте писать неудобно.

Так что да, в этом случае лучше уж на С писать, а точнее на удобном подмножестве С++

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

На Go можно выборочно для части программы или временно отключать GC?

Конечно, SetGCPercent(-1)

  1. Go был придуман Google с целью УДЕШЕВЛЕНИЯ разработки. Чтобы можно было писать простой код усилиями тысяч индусов

  2. Go был положительно встречен всеми потому что в момент его появления писать кровавый энтерпрайз на линуксе банально было нечем. Разработка на C/C++ идет слишком медленно, а джава была монстрообразна, а C# жил на windows платформе

  3. В Россию Go пришел как дань моды и у нас не получилось так что Go удешевляет разработку, наоборот, где требуется 1-2 Java/C# разработчика разработчиков Go для аналогичной системы нужно в 1.5-3 раза больше.

  4. Сейчас есть платформонезависимые экосистемы Rust, Java+Kotlin, C#/.NET каждая из которых стала лучше Go, но Go продолжает по инерции использоваться во многих проектах

Что ожидаю лично я. Поскольку Go изначально создавался с целью удешевления разработки то на нем будут писать ИИ-агенты и LLM. Он максимально простой и идеально впишется в новый мир разработки с применением ИИ. Что-то не нравится - ИИ перепишет говнокод на Go на другой говнокод который лучше и никакие индусы не нужны

Го придуман гуглом для замены Явы.

А Ии все равно, что генерировать.

Go был придуман Google с целью УДЕШЕВЛЕНИЯ разработки.

Любой мейнстримный язык, включая С, был придумал с целью удешевления разработки.

Чтобы можно было писать простой код усилиями тысяч индусов

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

 писать кровавый энтерпрайз

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

В Россию Go пришел как дань моды и у нас не получилось так что Go удешевляет разработку, наоборот, где требуется 1-2 Java/C# разработчика разработчиков Go для аналогичной системы нужно в 1.5-3 раза больше.

У "вас" это у кого? Если в вашей компании технологии выбирают по принципу "моды", это не значит что так у всех. Цифры про "в 3 разработчиков" вы на основе каких данных взяли?

Сейчас есть платформонезависимые экосистемы Rust, Java+Kotlin, C#/.NET каждая из которых стала лучше Go

Нет, не стала. Каждая из этих платформ имеет свои достоинства и недостатки по сравнению с Го, как с точки зрения разработки, так и с точки зрения выполнения.

Тонна слов и мало дел. Давайте соревнование устроим. Кидайте задания сюда и решения на го/раст и сравним что лучше

На розеттакод есть все готовое

Короче говоря, можно уже не переходить с php на go? А то я не успел)

Вот это отличная статья, куча статистики! Спасибо!

Безопасность типов и сопоставление с образцом

Эта претензия непонятна. В Го статическая типизация и есть интроспекция типов для матчинга. Лёгкая вариативность для удобства использования интерфейсов проблемой я не вижу

Вот мне интересно откуда автор знает какова ситуация в бигтех компаниях?

Наличие GC никого не останавливает использовать Kotlin или Java.

У Go есть своя конкретная ниша и осел там довольно уверенно. DevOps тулы не система реального времени. И только самый ярый фанат будет использовать его для написания игр или HFT

Но эпоха, когда Go был будущим программирования? Она угасает.

Go никогда и не был будущим программирования, он всегда был приветом из прошлого.

А уж для разработки крупных проектов его выбирали только вредители-саботажники. Он для этого максимально не подходит. И приносит компаниям только многомиллионные расходы на то, чтобы куча микросервисов хоть как-то продолжала работать и не разваливалась чаще раза в неделю.

В целом конечно особо не поспоришь ни с чем, но только не понимаю чего не хватает в IDE для go. Не то что бы большой опыт имею, но в том же Goland мне кажется есть всё что надо, да и обмазаться плагинами в vscode тоже думаю можно по самое не горюй

В Goland несомненно поддержка Go и инструменты реализованы на отличном уровне. Но в code-server и Cursor я лично не знаю как всё настроить, чтобы все необходимые инструменты были под рукой и чтобы дебаггер работал.

Опять Rust лобби пытается программировать молодежь :)

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации