Блог компании Нетология
Программирование
Карьера в IT-индустрии
Комментарии 83
+7
Golang (Go) — молодой, но набирающий популярность язык программирования.

Появился в 10 ноября 2009.
Не такой уж и молодой и его популярность давно ушла.
+1
Если его популярность давно ушла, то что же пришло ему на смену?
+3
Правильнее будет сказать, что хайп прошел. Когда бросались переписывать на Го, чтобы как все ну и Гугл же.
+18
Все, что существует на текущий момент, либо менее производительное (PHP, Ruby, Python), либо слишком сложное (C/C++, Rust), либо имеет проблемы с платформой и совместимостью с Linux (Java/Kotlin, Apple Swift).

Простите, а какие проблемы с совместимостью с Linux у Java?


Тащить в небольшие узкоспециализированные сервисы здоровенные фреймворки из мира монолитов не имело смысла, и все стали обращать внимание на Go.

А фреймворки из мира монолитов это что? Ну если не считать спринг, а взять какой-нибудь дотнет. Минимальной толщины ASP.Net Core, который просто занимается роутингом запросов? Нужен. ОРМ чтобы руками не маппить структуры на монги/постгресы? Дайте два. Работа с отказоустойчивостью из коробки (тот же Polly) не нужен? Да вроде нужен.


Но ничто из этого не монструозно, комбинируется в любых количествах как нужно, а жить без этого и писать SQL руками не очень. Да, я видел gorm, он ужасен. Особенно та часть, где нельзя сделать фильтр по дефолтному значению класса. То есть буквально Where(x => x == 0) не сделать. Это конечно обходится, но какой ценой. Про более сложные фильтры молчу, нужно изучать спецификацию конкретного орм, и строчками писать все тот же SQL. С таким подходом от ОРМ больше проблем, чем толку, соглашусь. Только это свойство не всех ОРМ вообще, а только данных.


Go достаточно простой язык.

На мой взгляд — слишком простой. В итоге 3party-библиотеку качественную просто физически невозможно написать. Остается только надеяться на милость std, что в очередной версии туда добавят то, что вам нужно. Наверное, с идеологией "всё своё, что не подходит — выкинем и перепишем" это не проблема, но у меня почему-то полное отторжение вызывает.

-6

C# хорош, и все могло сложиться совершенно иначе, если бы фишки .net core завезли году так 2010-2012. Но историю переписать нельзя, поэтому Go занял нишу микросервисов и консольных утилит, в блокчейне преуспел, да и в целом имеет более высокий уровень хайпа. Роб Пайк все давно уже все про него рассказал — в языке простые ортогональные фичи. Идеально подходит для тех, кто устал от сложности современного ООП (который, как известно, задумывался не таким), от всяких мракобесий вроде дефолтной реализации в интерфейсе и так далее. Эдакий С на стероидах.

+3
Не C, а Pascal на стероидах. Потому что у Pascal и Go — сильная типизация, процедурное программирование (да, то, что в Go вместо ООП, было описано уже в книге Энтони Хоара «Structured programming», там процедуры со структурами были связанные и пр., а гошные каналы (сиречь CSP) придумал Эдсгер Дейкстра примерно тогда же).
А вот за ad-hoc полиморфизм — жирный минус. Я не понимаю как такие великие (без всякой иронии) люди как Пайк, Гризмер и Керниган не увидели, что нужно делать либо динамическую типизацию, либо обобщённое программирование.

Простая задача: нужно написать полиморфную функцию, которая могла бы принимать на вход любую структуру, у которой есть поле ID типа int. (если кому-то подумалось, что это структура для отображения таблицы из базы, а ID — суррогатный ключ, то так и есть). В Go это НЕВОЗМОЖНО. Реализовать такое поведение можно, но это всё будут уродские способы.
1) Реализовать для каждого такого типа getter и setter методы для этого поля, создать интерфейс, состоящий из этих методов и передавать в полиморфную функцию интерфейс. Ужасающий копипаст и потенциальная сложность O(n) при изменении кода.
2) Принимать в полиморфной функции interface{} и использовать рефлексию. Которая расползётся как рак по всему коду и по праву считается в сообществе Go антипаттерном (хотя буквально все используют библиотеки, состоящие из использования reflect чуть более, чем полностью — для парсинга JSON, форм HTML, ответов из БД)
3) Принимать interface{} в полиморфной функции и написать развесистый switch, в каждой ветке которого пытаться кастануть interface{} в конкретный тип (опять же вернуть типизированное значение такая ф-ция не сможет, как и вариант с рефлексией, только вызвать другую функцию, а функций этих должно быть столько же, сколько типов и они должны быть написаны ручками). Это буквально пример из учебника как не надо проектировать программы и делать полиморфизм. Дядюшка Боб за такое откручивает головы.

Итого мы имеем Pascal с CSP, где вместо нормальных указателей (которые небезопасны, но хотя бы удобны по сравнению с Go) мы притворяемся, что ad-hoc полиморфизм это нормально и современно, а все, кто считает, что код должен быть гибким к изменениям, нужно соблюдать DRY, стремиться к single source of truth и избегать ситуаций, когда изменения в коде имеют сложность больше O(1), просто ничего не понимают в «простоте».
+2
Примерно так «наследование» делали в старые времена на Си. Нет, спасибо, я слишком много общался с сетевым стеком Linux и его «полиморфными» структурами.

А теперь представьте, что я согласен с Кристофером Дейтом и Джошом Беркусом (из PostgreSQL) и являюсь противником суррогатных ключей и хочу сделать полиморфные функции Create, Read, Update, Delete, все из которых принимают параметр — ключ, а он состоит из произвольного количества произвольных типов. Как в таком случае быть?
0

В материалах по Go трудно найти упоминания Pascal, а вот С встречается повсеместно. Более того, и компилятор, и прочие инструменты тоже сначала были написаны на С. И авторы языка сами по себе поклонники языка С. Так что я уверенно могу сказать, влияние и похожесть на этот язык много больше, чем pascal. Утверждение про csp не понял, зачем приведено, его ни в С, ни в Pascal нет. Я не знаток второго, но вроде это одного поля ягоды, во многом схожие языки. Буду признателен, если подчеркнете действительные отличия.


По поводу второй части — сам пример выглядит не очень показательным для минусов языка, можно найти и похуже что-то, но давайте обсудим тем не менее :) Я правильно понимаю, что в С, С++, С#, Java это тоже нереализуемо? Именно поле, свойство в С# не считается. Насколько я помню в них нет никаких контрактов на наличие поля в любой структуре.

0

Там написано "поле". "Поле" != "Свойство", вот такая простая логика. В чём тогда вызов? Ну да, синтаксически они выглядят одинаково, но на уровне реализации это совсем иная сущность. Плюс свойство может быть частью интерфейса, тогда задача тривиальна, но интерфейс опять-таки надо реализовать.
Хотя не исключаю, что задачу в своей интерпретации я излишне усложнил.

0

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

0

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

0

"Синтаксический сахар над вызовом специальных функций" — это и есть деталь реализации. Точно так же, как статическое выделение места в объекте является реализацией поля.


А семантика у них общая — в обоих случаях это некоторая переменная, привязанная к объекту/структуре.

0

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

0

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

0

Я, собственно, и не говорю, что это best practice, однако такое возможно в реальном коде, соответственно при чтении лучше различать семантику. Взять даже тривиальный пример реализации Singleton с помощью Lazy<> — фактически в момент вызова Value происходит некоторая магия, включающая в себя защиту от двойной инициализации в многопоточной среде, ещё какие-то нюансы. С доступом к полю разница весомая.
P.S. Семантика в смысле некоторой смысловой нагрузки. При абсолютном синтаксическом сходстве смысловая нагрузка другая. Мы ведь это обсуждаем? :)

0

Да, именно так, семантика в смысле смысловой нагрузки.


Взять даже тривиальный пример реализации Singleton с помощью Lazy<> — фактически в момент вызова Value происходит некоторая магия...

… о которой вызывающему коду знать не обязательно. Вот совсем-совсем необязательно.

+2

Только вот с этим сахаром работать удобно, а писать то же самое руками — неудобно. В джаве можно обойтись декораторами @Getter, в С++ есть шаблоны в которых это поле можно получить, в сишарпе есть {get;}, а в го что?


Мы же не аскетичным программированием занимаемся, чтобы себя ограничивать. Язык дает возможность — мы ей пользуемся. По-поводу "нечестно" — для выбора инструмента нет никакого понятия честности, есть понятие целесообразности и удобности. А то это как сравнивать Си с джавой, но запретить в последней пользоваться ООП "ведь в си его нет".

-1

Этот тред был про более узкую тему, а именно полиморфную функцию, принимающую любую структуру с полем ID. Пока решения не было в мейнстрим языках.
Касаемо Вашего замечания — в Go прямой доступ к полям, примерно как в Python, а-ля we are all adults here :)

0
Этот тред был про более узкую тему, а именно полиморфную функцию, принимающую любую структуру с полем ID. Пока решения не было в мейнстрим языках.

Все верно


void Foo<T: IHasId>(T x) {

}

Что в C#, что в Java, что в плюсах (там констрейинт правда не повесить вроде, но ошибка компиляции это почти то же в данном случае).

0

А чем вариант с интерфейсом Go в данном случае проигрывает? Так же будет функция, которая принимает IHasID, неявно реализованный.

0

А почему "неявно"? Насколько я знаю, поле в интерфейс включить нельзя, а метод придётся самому писать.

+2

То, что в сишарпе я напишу


class MyBar : IHasId {
    public int Id { get; set } = 547;
}

И всё само будет работать. А вариант без интерфейса выглядит так:


class MyBar {
    public int Id { get; set } = 547;
}

В данном случае сделать такой интерфейс нам практически бесплатно. Писать явно пары методов и прокидывать их в интерфейс не очень хочется. Мелочь, но если умножить на количество сущностей в коде оказывается очень прилично. У меня лично в текущем небольшом микросевриса 60 сущностей наследуемых от


interface IEntity { 
   Guid Id { get; } 
}
0

Т.е. вопрос свелся к тому, что свойства в C# удобнее пары метода? Ну на эту тему даже с Java можно похоливарить, не обязательно с Go :)

0

Да че тут холиварить, в джаве:


public class MyBar implements IHasId {
  @Getter @Setter private int id = 547;
}
-3
Ну да, давайте еще скажем, что в JavaScript есть каррирование, только потому что можно форк Babel сделать (по мотивам недавней статьи на Хабре) и там реализовать. Все, что не язык из коробки, не имеет смысла приводить в пример. Для Go тоже есть свои форки с наработками дженериков, но никто не говорит, что они есть в языке.
-4
В С это можно сделать и способы будут как раз похожи на описанные мною варианты (потому что interface{} — это по сути void *). Вдобавок есть довольно известный способ, когда создаются структуры, у которых первые n полей идут в одном порядке и имеют одинаковый тип (аналогично тому, что подсказал выше serge-phi ). Но на C никто веб-сервисы не пишет, правда удивительно?

В Java, C++, C# это реализуемо, притом элегантно, гибко и удобно.

Насчёт происхождения Go рекомендую посмотреть книгу «Язык программирования Go» Донована и Кернигана, где на 13-й странице показано, что Go происходит также от Pascal и Oberon. И ещё раз повторю: Go изначально задумывался строго типизированным — это настолько радикально отличает его от С, что я даже не знаю что тут ещё добавить.
0

Покажите пример на C#, так можем предметно его обсудить.

0
	interface IModel<Key, Data>
	{
		Key Insert(Data data);
		void Update(Key key, Data data);
		void Delete(Key key);
		Data Select(Key key);
	}
+1
Это точно решение первоначальной постановки?
нужно написать полиморфную функцию, которая могла бы принимать на вход любую структуру, у которой есть поле ID типа int

Ни полиморфной функции, ни поля ID типа int не вижу)
0
Это лучше, это решение более общего случая, который я раскрыл чуть ниже того комментария.
Полиморфная функция должна принимать на вход этот интерфейс. А при его реализации в случае с ID типа int нужно будет просто дать соотв. тип вместо Key.

P.S. Первый раз в жизни пишу на С#
0
Вот бы сейчас рассуждать про язык, на котором никогда не писал :)
Не обижайтесь, но это выглядит странно. Сначала ставите пусть и вырожденную, но вполне конкретную задачу, утверждаете о ее реализуемости, а затем приводите что-то совсем иное, и как оказывается на языке без практического опыта. Немного не то, что я ожидал.
+1

Ну нет, interface{} — это всё же не void*. Звезду Пустоты можно куда угодно скастовать, и если программист ошибся — то будет UB, в то время как в Go при неверном касте interface{} будет всего лишь паника.

-1
Пример про ID высосан из пальца. Достаточно передать в функцию сам ID в виде инта или указателя на инт. Надумали проблему и абсурдные решения. Отлично проводите время!

Ни какого «неудобства» в указателях go нет. Это ваша субъективная оценка, не надо её навязывать.
0

Отлично. Теперь кто-то ошибся, и передал сущность с id == 12, а качестве второго интового аргумента передал 10. Что в этом случае делать?

-2
Ответ очевиден. Предать в функцию DTO с явным указанием типа. Объяснить автору кода его не правоту — непонимание смысла статической типизации в Go. Мотивировать исправиться.
0

Мне тут подсказали, что в го есть некий go-derive, он не подойдет для решения задачи?

0
Поискал. Это генерация кода.
Вот вы на C# пишете. Рассудите — как вам эти решения, которые адепты Go предлагают на полном серьёзе?
Вот это, например: habr.com/ru/company/netologyru/blog/471782/#comment_20770976
Или этот goderive, который является по сути системой макросов для Go?
0

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


#[derive(HasId)]
pub struct MyFoo {
    id: i32
}

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

+1
Не понял последний абзац. Стандартную библиотеку пишут люди, преимущественно на Го. Почему для других это невозможно?
0

Ну например в Go1 есть генерики, но только для std. Никогда не замечали, что массив или мапа это генерик? Что функция append буквально объявлена как генерик func append(s []T, vs ...T) []T?


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

+1
А при чем тут библиотека? map, array, slice, channel — это встроенные типы (как int, string и т.д), append/make/new — это встроенные функции, а не библиотечные.
+2

Ну, реализация append вполне себе библиотечная функция, только называется она growslice


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

0
Нет, не могут. Каждое изменение языка (а добавление новой встроенной функции это и есть изменение языка) проходит длительный цикл обсуждения.
-2

Долго ждал момента чтобы написать :)
По хорошему это никакие не дженерики, а интринсики — т.е. подобные функциям встроенные средства компилятора. Нет в Go дженериков, что бы ни писали по этому поводу его пропоненты.

0

Окей, как скажете.


Тогда ответьте на вопрос, если мне нужно написать свой append, а встроенный интринсик по какой-то причине не подошел (например, я хочу добавлять элемент дважды), то как мне поступить? Или это "ненужно" и я делаю задачу не go way?

0

Вы неверно поняли мой комментарий. Я нигде не говорил, что дженериков нет и не надо. Я сказал как раз, что никаких дженериков там нет несмотря на все рассказы евангелистов про тот самый append. Это не более дженерик чем методы массивов в Java до 1.5. И да, они нужны чёрт побери.
Отвечая же на ваш вопрос — никак, без адских костылей как по приведённой ссылке growslice.

0
Вы неверно поняли мой комментарий. Я нигде не говорил, что дженериков нет и не надо. Я сказал как раз, что никаких дженериков там нет несмотря на все рассказы евангелистов про тот самый append.

Если что-то выглядит как утка и ходит как утка, то наверное это утка.

-3
какие проблемы с совместимостью с Linux у Java?
Как обновлять окружение на хостовой системе под новые версии приложения? Например, приложение перешло на новую версию java. Соответственно, ему нужна новая JVM плюс новые jar-ники на хостовой системе. При этом надо не поломать другие приложения на этой же системе, которые используют предыдущую версию JVM.
Минимальной толщины ASP.Net Core, который просто занимается роутингом запросов? Нужен.
С классами-контроллерами, DI и прочим хламом, да ещё и сжирающий пол сотни мегабайт ОЗУ, — не нужен.
ОРМ чтобы руками не маппить структуры на монги/постгресы?
Вы попутали ORM с кодогенерацией. В Go есть несколько утилит, которые это делают. Например, reform и github.com/go-pg/pg. Структуры монги мапить не надо, они сериализуются в json
Работа с отказоустойчивостью из коробки (тот же Polly) не нужен?
Разумеется не нужен. asp net дырявая и глючная, без заплаток не работает. А Go - один из самых надёжных языков из коробки после clojure и erlang. Меньше всего ошибок получается в программах на максимально простых языках.
Да, я видел gorm, он ужасен.
gorm нужен для сглаживания симптомов стокгольмского синдрома людям, пришедшим в Go из java/C#. Начиная с определённого уровня проф. развития sqlx + плагин jetbrains для баз данных полностью исчерпывают все нужды
нужно изучать спецификацию конкретного орм, и строчками писать все тот же SQL.
О ужас, бэкенд кодеру писать SQL да ещё и СТРОЧКАМИ. Как жить после этого? И вас конечно не смущает (или может вы не в курсе), что ни один комплексный проект на java/c# не обходится без написания SQL запросов вне зависимости от наличия или отсутствия ОРМ. Потому что ОРМ-ы на подобие EF покрывают дай Б-г 1% от возможностей SQL. Например, не умеют в рекурсивные структуры данных, а так же в специализированные, такие как json. Соответственно, ОРМ подходит по функциональности только в самых банальных кейсах, а в чуть более комплексных идут лесом.
3party-библиотеку качественную просто физически невозможно написать
Вы живете в танке и ни разу не сталкивались с докером и кубернетсом, написанными на го, или просто лукавите?
0
Как обновлять окружение на хостовой системе под новые версии приложения? Например, приложение перешло на новую версию java. Соответственно, ему нужна новая JVM плюс новые jar-ники на хостовой системе. При этом надо не поломать другие приложения на этой же системе, которые используют предыдущую версию JVM.

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


С классами-контроллерами, DI и прочим хламом, да ещё и сжирающий пол сотни мегабайт ОЗУ, — не нужен.

Citation needed. С бенчами, желательно. А то последний раз когда проверялось, оказалось, что го на 1-2% медленнее выходит.


Вы попутали ORM с кодогенерацией. В Go есть несколько утилит, которые это делают. Например, reform и github.com/go-pg/pg. Структуры монги мапить не надо, они сериализуются в json

Вот вы про этот?


err := db.Model(&Book{}).
    Column("author_id").
    ColumnExpr("count(*) AS book_count").
    Group("author_id").
    OrderExpr("book_count DESC").
    Select(&res)

Простите, это неюзабельно.


Разумеется не нужен. asp net дырявая и глючная, без заплаток не работает. А Go — один из самых надёжных языков из коробки после clojure и erlang. Меньше всего ошибок получается в программах на максимально простых языках.

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


gorm нужен для сглаживания симптомов стокгольмского синдрома людям, пришедшим в Go из java/C#. Начиная с определённого уровня проф. развития sqlx + плагин jetbrains для баз данных полностью исчерпывают все нужды

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


fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HLQDH7SGB0OC", Request id "0HLQDH7SGB0OC:00000005": An unhandled exception was thrown by the application.
System.InvalidCastException: Unable to cast object of type 'ValueCollection[System.String,MyCompany.Planning.Core.Models.PlanningTask]' to type 'MyCompany.Planning.Core.Models.PlanningTask[]'.

О ужас, бэкенд кодеру писать SQL да ещё и СТРОЧКАМИ. Как жить после этого?

Никак. В нормальных проектах этого не происходит.


И вас конечно не смущает (или может вы не в курсе), что ни один комплексный проект на java/c# не обходится без написания SQL запросов вне зависимости от наличия или отсутствия ОРМ

В моем текущем проекте 100% кода написано на LINQ который транслируется EFом в SQL. Но, конечно же, это неправильный я, игрушечный проект без серьёзной нагрузки, и вот это всё. В общем, ненастоящий шотландец.


Вы живете в танке и ни разу не сталкивались с докером и кубернетсом, написанными на го, или просто лукавите?

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

-1
Я из этого комментария сделал вывод, что я правильно начал изучать Clojure (который динамически типизированный и эта дурацкая проблемы про ID типа int там вообще не стоит, не говоря уже о том, что если Clojure как правило лаконичнее мейнстрим языков, то Go значительно более многословен, чем они)
-1
А приложения на Go компилируются в один бинарник без внешних зависимостей. Поэтому с ними очень просто работать на хостовой системе без необходимости заворачивать в докер — просто заливаешь новую версию бинарника на хостовую систему и перезапускаешь его.
При чем тут надежность языка?
И правда, какое отношение имеет надёжность языка к надёжности программ, написанных на языке
Надо бы сделать экспоненциальный бэкоф чтобы снизить нагрузку.
Так сделайте. Кто не даёт-то?
У вас язык лечит отказы веб-серверов написанных на других языках?
А зачем их лечить? Логгировать ошибку. Смотреть в кибане. Передать в прометеус метрики.
А с какого уровня опыта люди перестают делать ошибки, ловящиеся типизацией
С того уровня, который предполагает обязательное тестирование с тесовой БД. Ни разу у меня в продакшене на Go не было таких ошибок. Как же так получается, что я, по вашему мнению, не правильно готовлю БД на не правильном языке — и у меня ошибок маппинга нет. А вы на правильном языке с правильной ОРМ — и у вас ошибки маппинга есть. Что тут не стыкуется.
Никак. В нормальных проектах этого не происходит.
Ок, так и запишем: postgresql, мускул — это не нормально. Весь мир сошёл с ума, и лишь вы образец нормальности.
В моем текущем проекте 100% кода написано на LINQ который транслируется EFом в SQL
значит ваш проект действительно тривиальный в части коммуникации с БД. Либо вы самостоятельно реализуете функционал RDBMS серверов.
И нет, это не я придумал,
Серьёзно? и где там сказано, что «го на кубернетсах написали скорее вопреки, а не благодаря, не в последнюю очередь по политическим мотивам». По моему вы это именно придумали
0

Если бы вы ответили на мой комментарий, я бы ответил быстрее.


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

Мы даже питоновские скрипты состоящие из одного do_stuff.py в докер заворачиваем, потому что так удобнее с ними работать. Единообразие, так сказать.


И правда, какое отношение имеет надёжность языка к надёжности программ, написанных на языке

Вы про глюкавость asp.net по сравнению с го где прочитали? Давайте статистику, будем разбираться.


Так сделайте. Кто не даёт-то?

Язык не дает. Я же не дурак, писать стандартные вещи, надо взять и подключить библиотеку. Но вот беда, библиотеки нет, потому что написать её нельзя.


А зачем их лечить? Логгировать ошибку. Смотреть в кибане. Передать в прометеус метрики.

Кроме как залоггировать можно много чего сделать еще. Вы там посмотрите что Polly предлагает, там много политик.


С того уровня, который предполагает обязательное тестирование с тесовой БД. Ни разу у меня в продакшене на Go не было таких ошибок. Как же так получается, что я, по вашему мнению, не правильно готовлю БД на не правильном языке — и у меня ошибок маппинга нет. А вы на правильном языке с правильной ОРМ — и у вас ошибки маппинга есть. Что тут не стыкуется.

Ну так вы потратили время на написание теста и его проверку, а у меня типчики сошлись и тест писать не надо. Вы и сами знаете. в ЖС надо писать тесты на то, что функция работает если вместо числа передаешь мусор, а в го написал Int и мусор гарантированно не придет.


Ок, так и запишем: postgresql, мускул — это не нормально. Весь мир сошёл с ума, и лишь вы образец нормальности.

У меня постгрес, и SQL строчками я конечно же не пишу.


значит ваш проект действительно тривиальный в части коммуникации с БД. Либо вы самостоятельно реализуете функционал RDBMS серверов.

Даже в сложных проектах обходятся так. Редчайшие случаи когда нужно использовать функционал недоступный через общее АПИ (grouping sets, всякие аналитические функции прочее) бывают, но как правило все намного проще.


Серьёзно? и где там сказано, что «го на кубернетсах написали скорее вопреки, а не благодаря, не в последнюю очередь по политическим мотивам». По моему вы это именно придумали

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

0
Вы про глюкавость asp.net по сравнению с го где прочитали?
Я же ссылку давал на результаты исследования. Если язык надёжнее, то очевидно и библиотеки на нём надёжнее. И я не только прочитал, но вижу это в повседневной практике. С asp net постоянно проблемы, асинхронный код сложный и хрупкий.
Язык не дает. Я же не дурак, писать стандартные вещи, надо взять и подключить библиотеку.
Но Go нельзя реализовать exponential backoff? Хотелось бы понять, с чего вы это взяли, или шутить изволите. github.com/sethgrid/pester
Кроме как залоггировать можно много чего сделать еще. Вы там посмотрите что Polly предлагает, там много политик.
Можно, но нужно крайне редко. А в тех случаях, когда нужно, легко написать самому.
Ну так вы потратили время на написание теста и его проверку,
Нет. Я не пишу специальных тестов на проверку корректности маппинга, она побочно производится в процессе тестирования api. Если вы не тестируете свой api на тестовой БД, значит вы что-то делаете не так.
У меня постгрес, и SQL строчками я конечно же не пишу.
А у меня в постргресе хранится json, деревья, временные ряды, хранимые процедуры. Я так же часто использую рекурсивные структуры данных. ОРМ-ы в это всё чуть менее чем ни как.
Людям пришлось свою систему типов не от хорошей жизни выдумывать.
Вообще то нет. Люди необоснованно использовали питонизмы на ранней стадии развития проекта, вместо того, чтобы написать кодогенерацию. И всё таки, откуда прилетел вывод о политических мотивах написания K8s на Go? Теория заговора?
+1
Я же ссылку давал на результаты исследования. Если язык надёжнее, то очевидно и библиотеки на нём надёжнее. И я не только прочитал, но вижу это в повседневной практике.

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


И я не только прочитал, но вижу это в повседневной практике. С asp net постоянно проблемы, асинхронный код сложный и хрупкий.

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


Жс в котором багов меньше чем в хаскелле это просто "ха".


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


Но Go нельзя реализовать exponential backoff? Хотелось бы понять, с чего вы это взяли, или шутить изволите. github.com/sethgrid/pester

Но веть это не то. Вот есть у меня мой EthereumClient, который умеет в JSONRPC блокчейна. А блокчейн периодически ломается (реальный случай). Как мне быть в этом случае? В дотнете (взял из своего последнего проекта):


var web3 = Web3.Create(username: "0x09db118c3cab3e86487e591eed7cba1821750af8", "username", "password");
var mySmartContract = await MyContract.DeployAsync(web3);
var request = await Policy.Handle<Exception>(e => !(e is UnrecoverableBusinessException))
  .WaitAndRetryForeverAsync(n => TimeSpan.FromSeconds(5 * n),
    (ex, n) => Log.Warning(ex, "Error during request fetching"))
  .ExecuteAsync(() => mySmartContract.GetRequestsCountAsync());

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


Можно, но нужно крайне редко. А в тех случаях, когда нужно, легко написать самому.

Нет, не легко.


Нет. Я не пишу специальных тестов на проверку корректности маппинга, она побочно производится в процессе тестирования api. Если вы не тестируете свой api на тестовой БД, значит вы что-то делаете не так.

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


А у меня в постргресе хранится json, деревья, временные ряды, хранимые процедуры. Я так же часто использую рекурсивные структуры данных. ОРМ-ы в это всё чуть менее чем ни как.

Не вижу проблем с чем-либо. Я даже тот же postgis спокойно использовал через EF и никаких сложностей не испытал.


Вообще то нет. Люди необоснованно использовали питонизмы на ранней стадии развития проекта, вместо того, чтобы написать кодогенерацию. И всё таки, откуда прилетел вывод о политических мотивах написания K8s на Go? Теория заговора?

Теория политизированного решения и догфудинга.

-1
Это результаты исследования учёных из лаборатории IG Markets Ltd, а не просто статистика. Вы можете показать статистику, я могу назвать её фигнёй, и, скорее всего, буду прав. Но в данном случае речь о научном обосновании. Чтобы его опровергнуть, навешивания ярлыков да бабкиных сказок про чудесный хаскиль недостаточно. У вас есть учёная степень в области компьютерных наук? публикации в профильных научных изданиях? вот и пишите там аргументированные возражения как это принято в научной среде. А до тех пор они не слишком-то убедительны
Давайте конкретные примеры, разберем
Асинхронный код уродлив и состоит на 90% из хлама. Исчерпание асинхронного пула потоков. Асинхронные дэдлоки. Лок конвой на блокировках и IO. Абсолютно дебильная ситуация в целом, когда блокировки необходимы и их как бы даже можно использовать. Но на самом деле нельзя и надо их боятся.
Жс в котором багов меньше чем в хаскелле это просто «ха».
Я бы поспорил, но если у вас в жсе меньше багов чем а хаскелле то пожалуй смысла нет
.Разумеется, даже в самый дебильный язык, которым пользуются абсолютно все, в целом надёжнее маргинально-академического языка для ментального онанирования вприсядку.
+7
После Джавы единственное что нравится в Го это что на выходе один бинарник.
Все остальное оставляет впечатление сырого продукта.

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

Чем собирать проект? Так же, кто make, кто свое что то пишет, кто просто go ... и поехали, можно еще взять Bazel. и тогда начинается веселье, сделали go get ... потом не забыли натравить bazel gazelle ... который легко затирает модифицированные правила или bazel test не видит пользовательский aws конфиг или… все вообщем как то решаемо но хочется то легкости.

Решили тестировать, давайте моки подключим. В древней Джаве @Mock и поехали. В модном Го — сперва mockery -dir internal/cache -name PersonCache, который генерирует мок и кладет в файлик и только потом давайте его использовать. Добавили метод в исходный объект, поехали перегенерировать мок :)

И можно еще вспоминать кучу подобных вещей. Я бы не сказал, что Го простой и легкий язык. Что то быстро на коленки свалять и запустить, то да. Но я такое же быстро на Сприг Буте соберу. А если хочется скорости и памяти поменьше, то надо брать Rust.
+2
Для сборки java в бинарник уже есть graalvm, с появлением которого Go потерял единственное более-менее значимое преимущество перед java.
+1
«Куда класть исходники, как организовывать пакеты?»- смотреть в гугол: golang standards project layout

«Bazel» — это какая-то аберрация. Все проекты Go собираются командой go build с параметрами и тэгами. Или вы что-то делаете не так

«В модном Го — сперва mockery -dir» — и в чём проблема-то? Если «добавили метод в исходный объект», то всё равно тесты придётся переписывать. Чтобы меньше возится с тестами, используйте тестовые таблицы вместо моков

-2
смотреть в гугол: golang standards project layout

в джава такого вопроса даже не возникает.

Все проекты Go собираются командой go build с параметрами и тэгами. Или вы что-то делаете не так

go build вы соберете какой либо один бинарник. А как быть когда надо прогнать тесты, потом интеграционные тесты, собрать пару бинарников да еще под разные платформы, все упаковать с нужными конфигами и тд, то что вы делаете? Да так чтобы еще все собиралось без танцев на разных машинах у разработчиков и в Дженкинсе.

и в чём проблема-то?
— проблема в дополнительном телодвижение. Или как мне сделать spy?

Чтобы меньше возится с тестами, используйте тестовые таблицы вместо моков
как тестовые таблицы отменяют моки?
Вот для примера сравните как делается в Джаве: junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
нет никакого кода не нужно для теста, а именно:
for _, tt := range fibTests {
actual := Fib(tt.n)


Те мой коментарий был не о том какой Го плохой, а о том что он сырой еще. И на разработку времени тратится больше без какого либо видного профита на выходе.
0
«в джава такого вопроса даже не возникает» — так ведь должен возникать.

«А как быть когда надо прогнать тесты» — я использую JFrog Artifactory и средства IDE для CI. Не понял в чём там принципиальные отличия worflow на Go от java. И с чего бы Go был хуже java приспособлен для CI, если Go обычно компилируются в один бинарник без внешних зависимостей. А типичное приложением на java( c#, node.js, php, python) зачастую имеет кучу внешних зависимостей, в т.ч. и системных, и которые невозможно нормально обновлять и поддерживать в работоспособном состоянии на хостовой системе без использования докера.

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

«Вот для примера сравните как делается в Джаве:» — это вкусовщина. Кому то нравится указывать тестовые метаданные. Я предпочитаю ясность — явно указывать в коде всё, что относится к тестам. Это способ, предпочтительный для Go. Любой кодер уровня мидл без труда освоит оба способа.

«И на разработку времени тратится больше без какого либо видного профита на выходе.» — а как же сотни крупных мелких компаний, переходящих с других языков программирования на Go? Если это технически не обосновано, то почему ни кто не рассказывает как он вернулся обратно на java? И почему получается, что сервисы, написанные на Go, обходятся в 10 раз дешевле аналогичных сервисов на Java-подобных языках на AWS Lambda? Несмотря на то, что теоретически в java на много больше возможностей по оптимизации для быстродействия. Предлагаю такое объяснение этих фактов — Go против бесполезных абстракций из java.
+1
так ведь должен возникать.
зачем? Я не хочу парить голову и пытаться понять где что лежит и как что собирать и проверять.

Не понял в чём там принципиальные отличия worflow на Go от java.
— отличие в том, что в джаве есть отточенный мавен. А как в Го вы собираете бинарники для разных платформ? как конфиги пакуете вместе с приложением или какие то срипты и все это потом собираете в докер образ? И как это делают в другой компании, а потом в третьей — мне кажется у каждого будет какой то свой зоопарк велосипедов.

Две достаточно взаимоисключающие парадигмы

с этим я согласен но это же вы написали:
Чтобы меньше возится с тестами, используйте тестовые таблицы вместо моков


явно указывать в коде всё, что относится к тестам.

это не явно указывать — мы сделали функцию которая возращает тестовые данные а потом в каждом тесте пишете код в котором итерируете по этим данным. Те просто код который копируется из теста в тест без всякого смысла. Если платят за строки кода и если вспомнить if err != nil { return err} на каждый чих то Го конечно вне конкуренции :)))

Насчет хайпа — то я помню хайп насчет подобный скайп вокруг ruby on rails или scala.
То что кто то вокруг кричит и пиарит Го, не значит все бросают java и переходят на Го.
Простой запрос в гугл java job дает 521М, golang job — 6M, hh.ru — java — 2755 вакансий, golang — 281

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

Я не против Го, сам пописываю на нем либо лямбды(когда надоедает на ЖС :) ) либо какие то утилиты. Но я не вижу причины почему мне надо делать очередной микросервис на нем а не на Джаве, а тем более соваться в ентерпрайз. Для меня в нем нет вау эффекта как от Раста, в нем нет безумной производительности, в нем большое кол-во бойлер плейт кода, моя продуктивность ниже чем при написании на Джаве.
+6
Никому не показалось, что если в статье сделать Ctrl+R: Go/Python то ничего принципиально не изменится?
0
Попробовали Go — уменьшили потребление памяти в несколько раз.

Хм… А есть ли какие-нибудь опубликованные бенчмарки Java vs Go? Про GC в Go, например, пишут, что короткие паузы достигаются ценой большего расхода CPU при сборке и большего футпринта в памяти.

+1
benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/go.html

Меньшее потребление памяти и более высокая скорость достигаются за счет того, что Go умеет держать объекты на стеке. Но Java (и С#) выигрывает в сценариях, когда выживает много молодых объектов (это хорошо иллюстрирует тест binary-trees).
+1
Преимущества Go с технической стороны совсем незначительны по сравнению с его мощной поддержкой от вендора. Здесь чисто внешняя экономика.
0
Я бы не сказал, что незначительны. Благодаря консервативному сборщику мусора Go открывается много возможностей для оптимизации (и возможностей выстрелить себе в ногу), по типу такого: github.com/pi/goal/blob/master/internal/tests/benchmarkgame-binarytrees/binarytrees.go
Ускорение binary-trees почти до уровня оптимизированного С
0
А в чём эта поддержка от вендора заключается?
Тут есть и обратная сторона: уже было заявлено вслух и под запись, что Go был создан для решения проблемы Google — множества разработчиков только из колледжа, которые не умеют толком программировать, поэтому им нужен простой язык, который бы подходил для решения типовых гугловских задач.
0
Вендор нанял людей масштаба Ритчи, Томпсона и Пайка. Если бы не вендор, то Go так бы и остался «in limbo».

Для молодежи: en.wikipedia.org/wiki/Brian_Kernighan

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

P.S. Пайк — один из создателей UTF-8
0
Во-первых Брайан Керниган жив, во-вторых, он соавтор одной из книг по Go. Может быть вы имели в виду Денниса Ритчи?
0
evocatus
нужен простой язык, который бы подходил для решения типовых гугловских задач
Согласен: нишевость — это еще одно преимущество Go. Или недостаток?

serge-phi
… открывается много возможностей для оптимизации…,… ускорение binary-trees почти до уровня оптимизированного С
Этого мало, чтобы взлетел новый промышленный ЯП. А также уже у кого-то это есть и сейчас.
0
Не удалось найти поиском в статье и комментариях, почему разработчики выбирают Go вместо Rust (схожие по положению ЯП). Если Rust может помимо детских проблем индустриальной разработки внести кое-какие новые интересные принципы, то что принесёт Go непонятно (кроме горутин, которые чаще всего не особо нужны).
0
Вот уверен, что Go взлетит (или уже взлетел) в узкой нише микросервисов благодаря только мощной поддержке вендора. А Rust может вообще не взлететь, так как ИМХО становится похожим на С++, только сложнее с точки зрения обучения.
+1
становится похожим на С++, только сложнее с точки зрения обучения.
Мне кажется, что наоборот и в экспоненте. Чтобы продуктивно и качественно писать на С++, нужны экстраординарные усилия. Теоретически как раз Rust может дать небольшую кривую обучения для более менее хорошего quality.
Только полноправные пользователи могут оставлять комментарии., пожалуйста.