Комментарии 31
Golang это "си для кластеров", но рафинированный, чтобы поменьше стрелять себе в ногу -- это понятно, средний уровень разработчика теперь пониже, зато серверов и программистов у гугла много. Си был довольно простым и ограниченным языком для написания одностраничных утилит под стиль unix, Го это тоже самое, только юникс теперь распределенный
Кажется вы не до конца понимаете значение слова тоталитарный) Go не заставляет и не запрещает, он просто дает набор возможностей. Возможно набор небогатый, но достаточный)
Более того, насколько я понимаю, он особо не ограничивает фантазию. Кто-то может работать с ошибками через panic() или глобальную last_error, синхронизировать goroutines через классические мьютексы и эмулировать наследование используя generics, интерфейсы и embedded structs (хотя учитывая то как хейтят сейчас ООП, думаю таких найдется немного)
Go как раз заставляет, запрещает и дистимулирует
Можно ли работать с ошибками через panic? Можно, но это очень не удобно, потому что в std и сторонних библиотеках принято использовать error, получится смешение подходов, которые еще нужно как-то соединять
Можно ли сихронизировать горутины через классические мьютексы? Да, но зачем, если есть sync.Mutex?
Можно ли эмулировать наследование через embedding? И да и нет, полноценного наследования все-равно не получится. Методы и поля через embedding невозможно переопределить так
Возможно набор небогатый, но достаточный)
Согласен, в этом и суть! Есть все, что нужно для бекенд разработки, ни больше ни меньше. В этом и суть "тоталитарности", дать разрабу достаточно функциональности, чтобы он мог эффективно писать код, а также чтобы он не изобретал велосипед, при этом не слишком много фичей, чтобы он не было зоопарка реализаций
Я понимаю вашу точку зрения и сам лично приветствую философию Go. Но вот только «тоталитарный» это совсем другое.
Это не когда, «неудобно», «некрасиво» или «не нужно», а когда запрещено и жестко наказуемо. И не собственным чувством прекрасного, а государством или близким к нему по степени власти над вами органом.
Можно было бы привести примеры, но не хочется тут уходить в политику, каждый может сам найти при желании.
В богатой доменной модели Go плетётся в хвосте.
Rust > C#>Java>PHP>Go
Rust - sum types (enum), pattern matching, трейты, ownership - отлично ложится на domain modeling в духе Влашина ("Making Illegal States Unrepresentable").
C# подтянулся: records, discriminated unions пока нет нативно. Java - sealed classes, но многословно. PHP - слабая типизация мешает.
Go в хвосте: нет enum с данными, нет дженериков до недавнего (и они слабые), error handling через if err != nil - домен тонет в бойлерплейте. Structs + interfaces - плоская модель, сложные инварианты выражать тяжело.
Но Go и не для этого. Его ниша (ой, тут утверждали про тотальность/универсальность?) - сетевые сервисы с простой доменной логикой, где anemic model + процедурный стиль нормально работает. Проблема когда на Go пытаются писать сложный домен - получается месиво.
Второй большой недостаток - го не может вызвать или быть вызванным из других программ, только по сети.
Нет иммутабельности значит нет функционалльного программирования нормального, но ООП тоже нет. Остаётся процедурный стиль со структурами и интерфейсами. По сути это улучшенный C из 70х с GC и горутинами
Это с чем столкнулся
Ну и ещё десяток недостатков...
Согласен, собственно поэтому Go и используют только в бекенде и инфраструктуре бекенда, а в геймдеве, фронте, мобилке, системной разработке и тд его почти никогда не используют
Тогда непонятно о чем статья
Про философию Go "one way to do it"?
О основной фишки голэнга - тоталитарности, что ограничивает возможности разработчика
Я не писал о том, что Го надо использовать везде и ко всему или что его дизайн самый лучший, я писал о том, что сам Го уникален не горутинами, а ограничениями
И это не плюс или минус, это как функциональшина хаскеля или боровчекер в расте - фишка языка, которая определяет его и его использование
Но разве в Java нет горутин?
Нет
Как можно сравнивать Go и Java ? Java это тормозное корпоративное болото в котором никто не считает никакие ресурсы...ни машинные, ни человеческие. Go программа будет работать на 90% target машин сразу,а Java вы сначала замучаетесь искать нужную версию,а потом все бросите и пойдете переустанавливать новую систему потому что нужной версии java нет даже для не старой версии системы. Вот как раз недавно имел занимательное развлечение с UniFi network server который вдруг решили обновить Java 17 на Java 25, только эти "эффективные" программисты забыли что рекомендуемая ими Debian 12 Bookworm (вышедшая всего 2 года назад) НЕ ИМЕЕТ Java25 headless. Т.е. теперь все клиенты должны или обновить систему до Debian 13 или поставить гигабайты X11+ вместе с полной версией Java25 , чтобы просто работал простенький web server. Думаю что если бы они писали на Go, то все уместилось бы в десяток мегабайт и работало бы на системах 20 летней давности. Вот поэтому люди и выбирают Go, а не потому что в Java тоже НЕТ горутин.
Щас не понял, композиция это реально минус для кого то? Надо быть тяжело промытым в мозгах, чтоб любить наследование
Любить наследование необязательно, а вот уметь использовать, где оно есть - надо : )
А может быть это с вами что то не так раз вам проще 100 раз сделать Copy-Paste вместо наследования? Я люблю наследование, более того...бывает что в языках, отличных от С++ мне не хватает множественно наследования. И у меня никогда небыло проблем с поддержкой проектов с множественным наследованием. Если же язык не поддерживает классы и наследования, то все равно их концепция может быть реализована, просто будет намного более не красиво и сложнее в поддержке, но вы все равно тем или иным способом будете это использовать потому что альтернатива это copy-paste
У наследования есть прекрасная не copy-paste альтернатива - композиция :)
Вы наверное не понимаете что такое композиция и чем она отличается от наследования.Композиция работает когда вы хотите использовать готовый функционал готового класса и ему не нужен доступ к вашему классу потому что он уже полностью готов и самодостаточен. Вы не можете переопределить ничего при композиции не меняя интерфейсам взаимодействия с классом, который используете при композиции. А наследование подразумевает что родительский класс имеет полный доступ к наследнику и вы можете менять логику родительского класса БЕЗ изменения интерфейса взаимодействия. Возмем простой пример. У вас есть класс который реализует список (list) чисел вы ходите сделать класс который его расширяет и делает его упорядоченным списком. При наследовании я просто наследуюсь от него и переопредяляю метод добавления чтобы он вставлял не в конец, а в нужное место согласно нужному порядку....все, переопределил 1 метод и готово. А теперь сделайте тоже самое композицией чтобы я мог передать любой из этих классов одному методу. В лучшем случае для этого надо будет определить интерфейс, потом сделать класс заготовки списка с доступом ко всем его элементам, и только после этого вы сможет включить этот класс в композицию финальных классов где уже реализуете интерфейс используя copy-paste для обоих классов. И при каждом изменении интерфейса вы должны менять все где он упоминается и реализован. И что будет проще поддерживать и использовать?
Много букв, мало знаний.
Есть яп, для которых композиция неявно переписывается как вызов метода и наоборот.
Включая даже мультиметоды. Там же список яп
Мало букв, ноль знаний. Сразу видно "господина" теоретика, который не написал ни одной реальной строчки кода в своей жизни. В мире есть много чего (кроме конечно ваших знаний, вот чего нет так уж нет...даже больше нескольких предложений воды не осилили). Вы можете извращатся как хотите, это ваше дело как эмулировать наследование, но проще и лучше от этого не становится ни код ни его поддержка. Для начала автор хотябы должен разъяснить чем по его мнению композиция лучше наследования и как он использует эту "альтернативу" в конкретном примере. Ну от ответить лучше с аргументами, а не ссылками на wiki про мультиметоды пытаясь сойти за умного. Ум проявляется в делах, а не ссылках на чужие слова. Давайте пример как вы обходите наследование композицией с переписыванимем методов в месте со статьей как вы потом будете это поддерживать, если конечно вас раньше не сожгут на костре за такое издевательство. А потом и сравним что проще и кому промыли что то. Только делайте это на языке который поддерживает и наследование и композицию, а дальше хоть мультиметодами, хоть корягами, главное чтобы проще, нагляднее и понятнее чем наследование. Вот мы тут посмеемся.
А в каком месте вы привели пример Композиции на Go?
Если вы про этот код:
type UserService struct{
cache Cache
}
type Cache interface{
Get(k string) (string, error)
Set(k, v string) error
}
type MapCache struct {/* ... */}
type MapCacheThreadSafe struct {/* ... */}
type RedisCache struct {/* ... */}Так тут, пардон, — её нет, это Агрегация.
Но главный вопрос к "тоталитарности" интерфейсов в Go:
В чем преимущества "гадания" в Go — подходит ли структура под интерфейс, который нигде не задается явно при реализации, — перед явным объявлением в Python?
class Cache(abc.ABC):
@abc.abstractmethod
def get(self, k: str) -> str: ...
@abc.abstractmethod
def set(self, k: str, v: str) -> None: ...
class MapCache(Cache):
def get(self, k: str) -> str: ...
def set(self, k: str, v: str) -> None: ...
class RedisCache(Cache):
def get(self, k: str) -> str: ...
def set(self, k: str, v: str) -> None: ...В Python я вижу, что класс наследуется от Cache и согласно LSP обязан следовать контракту родителя.
В Go же, чтобы понять, что, например, структура MapCache вообще имеет отношение к интерфейсу Cache, мне нужно откуда-то догадаться, что где-то объявлен такой интерфейс.
Где здесь та самая "тоталитарность", которая якобы упрощает жизнь и снимает вопросы? И как насчет последовательности дизайна языка? Куда вдруг пропала явная типизация - и всплыла "уточка типизации"? : )
Встраивание Кеша в UserService как раз пример композиции
Тоталитарность Го тут проявляется в том, что в питоне есть 5 способов, как можно сделать одну задачу. В данном примере можно протоколы использовать, а можно асбтрактные классы. Один разраб одно будет использовать, другой другое. А в Го - только интерфейсы, даже если интерфейсы тут хуже, чем абстрактные классы
Go — замечательный язык для своей ниши: инфраструктурные сервисы, CLI-утилиты, всё, что должно компилироваться в один бинарник и предсказуемо работать. Его ограниченность — это плата за попадание в эту нишу, а не философский идеал. Назвать это "тоталитарностью" и представить как главное преимущество — красиво, но по сути это эвфемизм для "узкой специализации". Как только язык попытается выйти за пределы этой ниши, его "тоталитарность" начнет трещать по швам, и он неизбежно начнет обрастать теми самыми сложными конструкциями, до которых у фанатов языка и дело ввиду их сферы разработки редко доходит.
Так и речь не о том, чтобы делать из Go язык на все случаи жизни, а о том, что автор сравнивает и "удивляется": и зачем в других языках все эти сложности, которых нет в Go? : ) Так это не потому, что Go нашёл программистский универсальный Грааль, а потому что это хороший инструмент для конкретной сферы. У других языков — другие сферы, отсюда и другой инструментарий.
Так я, автор, и не говорю, что Go это Грааль или идеал, а просто хороший инструмент под конкретную задачу
(надо было секцию "Минусы" побольше описать...)
А зачем тогда сравнивать его с языками, явно другого поля применения, такими как - Java, Python, да и Rust?
Вы берете, условно говоря, трековую машину - с максимально обтекаемым силуэтом и прижатую к земле, у которой из салона выкинуто всё "лишнее" а вместо этого "лишнего" - установлен каркас безопасности... и сравниваете её с седаном, на котором ездят на работу каждый день, или с пикапом, в котором грузы возят - и говорите: во, зачем им этот салон, где усилители, почему такие высокие - их же раскачивать будет в поворотах!... : )))
И опять - речь не про то, что Go, условно - плох на "бездорожье" : ) ему туда по-сути и не надо, а о том, что если уж и имело смысл сравнивать - так это "машины" одного назначения.
А если делать "многоцелевую" машину - то вот тут и полезут компромиссы : )
Так Rust, Python и Java используют часто в тех же задачах, что и Go
По вашей же аналогии я сравниваю седан, трековую машину и пикап, которые втроем приехали на ралийные соревнования
Конечно я буду их сравнивать
Python и Java - в первую очередь языки для описания сложных доменов - для этого у них и есть соответствующие инструменты, которые позволяют без лишнего скрипа, а пожалуй что - и комфортно, описывать то, для чего они и были созданы. В инфраструктурных задачах они будут проигрывать языкам, заточенных под построение инфраструктуры, как те, в свою очередь, будут вынуждать писать логику какими-то нетривиальными подходами - потому что нет объектов, нет элементарных enum.
Я нигде и не утверждаю, что Python и Java - лучше во всём : ) потому что это элементарно не так, потому что область применения неизбежно диктует наиболее подходящий дизайн языка программирования, и чем более специфицируешься - и получаешь удобные плюшки для ниши, тем менее становишься универсальным. Всё имеет свою цену - и спецификация, и универсальность.
Rust - и вовсе выбор для системного программирования. Да, и на нём можно писать всё остальное - но это, утрируя, как забивать гвозди микроскопом. На каком-то уровне - сойдет; если нужна максимальная эффективность - будешь страдать.
Или вы будете утверждать, что таки Go - это и великолепный швец, и жнец, и на дуде игрец, ибо реализовал "тоталитарность"? : )
Ява прямой конкурент Го.
Разве что создавалась в эпоху мейнфреймов в серьёзном бизнесе, и несёт многое оттуда.
А Питон это вообще не отсюда. Но его суют везде, с известным результатом.
Java моложе Python : )
И про мейнфреймы — это, мягко говоря, натяжка. Java создавалась как "write once, run anywhere" для разнородных систем, а не для мейнфреймов. Но это к делу не относится.
Суть в другом: и Java, и Python — языки широкого профиля, каждый со своей историей и компромиссами. Go — язык узкой специализации. И это не делает его "хуже" или "лучше". Просто разное назначение. А когда начинают сравнивать специализированный инструмент с универсальным и удивляться, почему у второго якобы "лишние" детали — это странно : )
Посоветуйте статью от такого же увлечённого товарища о Rust

Тоталитарный Golang