Pull to refresh

Comments 369

Вторая программа выводит на экран:
2009/11/10 23:00:00 Working with a=47, b=0

Не понял претензии в этом случае. Мы добавили в структуру еще одно поле, явно не указали ему значение, оно инициализировалось нулем, передали структуру в функцию и она нам распечатала значение. Что не так? Компилятор должен был выдать ошибку из-за того, что мы не указали явно значение поля структуры?

В сущности, мы изменили сигнатуру функции,

Но ведь сигнатура функции не поменялась, она как принимала на вход структуру Params, так и принимает

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

Да, добавлю лишь то, что в Rust вы не можете инициализировать структуру, которая не реализует trait Default, не указав все поля, которые есть. И даже если реализует этот trait, в инициализаторе явно надо писать ..Default::default() вроде, показывая что остальные поля будут инициализированы значениями по умолчанию

Зато когда вы напишите ..Default::default() вам откроется уникальная возможность добавить новое поле, забыв его проинициализировать

Не совсем так - это будет ровно такое же поведение что и в Go, т.е. инициализация значением по умолчанию, но это явно и вы для этого должны приложить усилия (либо руками реализуя Default либо через #[derive(Default)]), в отличии от неявного поведения, которое никак не выражено синтаксически в вашем коде.

Совершенно согласен с утверждением, что явное лучше не явного
Иметь возможность обязательно инициировать все поля и иметь возможность явно прописать когда это не нужно - очень хорошо
Но лично я - буду за именно обратный путь, меня устроит если появится возможность объявлять структуры так, чтобы при их инициализации нужно было бы инициализировать все поля
Это именно путь когда инструменты языка сужают возможности, а не расширяют
Имхо такой путь прозрачней
Правда кто я такой чтобы моё мнение кого-то волновало ))

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

Подождите, в Rust же именно так и есть? или я вас не понял? Как раз в нем если ничего не указывать явно (с помощью derive), не реализовывать Default trait, будет именно такое поведение

У меня была нужда проверять автоматически, что структура заполнена. Это были структуры со словом Config в названии. Для этого можно легко настроить линтер. Работает отлично и спасало

Эта штука в Go напоминает проблему null'ов, по какой-то причуде названной фичей и расширенной. Всё-таки лучше, когда возможность отсутствующих значений явно прописана ввиде Option<Value or None> вместо того чтобы ожидать их везде.

Ну в этом ведь и состоит дао Го (явно унаследованное от юниксового KISS): не надо тратить лишнее время чтобы настучать это самое ..Default::default() (горизонтальное и два вертикальных двоеточия, ух), а потом ещё ходить по декларациям и проверять, где оно прописано. Все структуры ведут себя в этом аспекте одинаково. Простота как она есть.

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

зачем вам знать количество полей? Просто заполняйте те, которые нужны или используйте "конструктор"

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

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

import std.stdio, std.traits, std.format;

struct Params {
	mixin Strict;
	int a;
	int b;
}

void work( Params p ) {
	writeln( "Working with ", p );
}

void main() {
	work( Params(47) );
	/+
		Error: none of the overloads of `this` are callable using argument types `(int)`
			Candidate is: `onlineapp.Params.Strict!().this(int _param_0, int _param_1)`
	+/
}


mixin template Strict() {

	@disable this();

	this( FieldTypeTuple!(typeof(this)) args ) {
		static foreach( Index, Field; FieldNameTuple!(typeof(this)) ) {
			mixin( format( q{ this.%s = args[ %s ]; }, Field, Index ) );
		}
	}

}

В Go можно использовать обёртку Optional, если уж прям очень хочется для примитивов понимание "был параметр явно присвоен или нет: https://pkg.go.dev/github.com/searKing/golang@v1.1.18/go/util/optional

Правда есть минус - теперь мы "потеряли" тип примитива и должны его знать

import "github.com/searKing/golang/go/util/optional"

type Params struct {   
  a optional.Optional   
  b optional.Optional
}

func work(p Params) {   
  log.Printf("Working with a=%d, b=%d", p.a.Get(), p.b.Get())
  if p.a.IsPresent() {
    log.Printf("calc: %d", 1+p.a.Get().(int))
  }
  if p.b.IsPresent() {
    log.Printf("calc: %d", 1+p.b.Get().(int))
  }
}
func main() {
  work(
    Params{
      b: optional.Of(2),
    },
  )
}

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

Не говоря о НЕтипобеопасности

ну, можно и так - тут потери типа уже нет. Правда теперь в лог пишется адрес, а не значение поля. Но тут либо шашечки (примитивы с default value), либо ехать

type Params struct {
	a *int
	b *int
}

func work(p Params) {
	log.Printf("params: %++v", p)
  log.Printf("calc: %d", 1 + *p.a)
}

func main() {
	a := 2
	
	p := Params{a: &a}
}

А про обязательность поля - по мне, так это достаточно удобно , когда примитив можно явно не указывать и ему присваивается default value - меньше писанины. На то он и примитив, а не объект

когда примитив можно явно не указывать и ему присваивается default value

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

Далеко не всегда default value типа имеет какой-либо смысл в реальном мире в том контексте, в котором этот тип используется в структуре. Хотя ладно: когда его нет, это ещё ничего, хуже, когда это значение по умолчанию смысл реально имеет - и потом поди догадайся, забыл автор его инициализировать или там и правда этот нолик стоит и с ним нужно работать (и, например, дебажить, почему у вас где-то косяк в коде дальше - проблема в вашей логике или этот нолик забыли инициализировать, что привело к неконсистентному состоянию данных в этой структуре).

У нас есть проект, где бэк на Go, где вот так приходит факт, что поле author пустое у объекта
{ title: "", author: { id: "", firstName: "", lastName: "" } }
Или enum'ы приходят так { someEnum: "XXX_UNKNOWN", } опять же потому что "XXX_UNKNOWN" — это дефолтное значение.
Очень часто в данных есть огромная разница между 0 и Some(0).

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

да

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

Да. Честно, я не понимаю, зачем эту "фичу" вообще реализовали, она даже больше кода в компиляторе требует.

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

Этот код не скомпилируется:

package main

import "log"

type Params struct {
	a int32
	b int32
}

func work(p Params) {
	log.Printf("Working with a=%v, b=%v", p.a, p.b)
}

func main() {
	work(Params{
		47,
  }) // <- Error: too few values in struct literal
}

Так ещё лучше: получается, что, чтобы Go выдал ошибку, нам нужно не учитывать имена полей, а вместо этого держать в голове их порядок?

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

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

Можно указывать, но можно и не указывать. А если указали, то не обессудьте - вот тут для вашего удобства у нас такое поведение дополнительно зашито, читайте справочник по нашему самому простому языку в мире, стр 1531, третий абзац снизу. Я бы ещё понял, если бы дефолтное значение задавалось явно, как kwargs в питоне:

type Params struct {
	a int32
	b int32 = 0
}

Не надо держать. IDE подсветит.

В первом случае я указал явно field `a` со значением, тогда b будет иметь значение `0` по умолчани.

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

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

Мне например проще управляться с указателями, чем понять код где через слово self-self-self или this-this-this.

Потому что он топит за Раст, очевидно же, хотя это и языки с совершенно разными применениями и скоупом. Для 2022 года довольно типичный rant. Сейчас вот смотрю плашку справа, Go 122 вакансии, Rust 21 -- не даёт покоя это любителям раста аж до скрежета зубовного, кушать не могут.

Нет, вы это сами себе придумали. :)

Не пишу на Раст. Не топлю за переход на один конкретный язык. Это не мешает мне утверждать, что Go - пример отвратительного языкового дизайна, и для того, чтобы стало лучше, чем с ним (если вы конечно не фанатик), достаточно сменить язык на любой другой популярный, подходящий по предметной области. В фронте есть тайпскрипт, в бэке - что угодно от C++ (там конечно своих can of worms хватает), языков с явным рантаймом вроде Java/Kotlin/Scala и C#/F#, и до вещей для любителей экзоткики вроде Haskell.

Amos? Не узнаю в гриме.

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

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

Автор статьи Amos Wenger -- поэтому мне непонятны слова "Нет, вы это сами себе придумали. :)" от кого-то, кроме него. Только он может это сказать.

Я высказываю своё субъективное мнение относительно того, какую цель имела эта статья в конкретном треде под конкретным комментарием об этом -- и если бы в ней не было прямого указания Раста, это мнение было бы другим.

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

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

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

Я уже написал всё, что хотел -- я считаю, что автор под критикой Го прикрывает продвижение Раста. Sapienti sat, dixi.

P.S. В обсуждении на HN упоминаний Раста 111 штук: https://news.ycombinator.com/item?id=31205072 Без комментариев.

Я тоже dixi, в общем-то, но повторюсь: - вместо того, чтобы комментировать статью, вы комментируете действия автора (хотя даже если всего лишь прочитать статью в оригинале - перевод листал по диагонали - можно увидеть, что такие смехотворные попытки дискредитации там тоже прокомментированы, и "почему тут упоминается Раст так много, и почему это на самом деле не имеет значения" в том числе).

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

Мне кажется он просто боится клешни отрастить и начать питаться падалью из-за частого упоминания Rust. Хорошо что языки программирования на самом деле не заразные.

Прям таки и большой выбор языков для бэка... Тащить java и производные либо отдаться мелкомягким? Просто отличный выбор :)

А остальные языки уже не компилируются что ли?

Для бэка довольно много языков по факту. Если опираться на аргумент "у Go такая привлекательная асинхронная среда выполнения и сборщик мусора, что они компенсируют все остальное", то можно в качестве альтернативы взять упомянутый в статье Elixir, у которого и асинхронная среда выполнения и сборщик мусора сильно лучше, чем у Go. К тому же, при необходимости в него можно добавить щепотку Rust, если вам где-то в проекте нужна числодробилка.

UFO just landed and posted this here

Человек дальше джавашарпа носа не высовывал, а вы его пугаете совсем иной парадигмой.

Ближе всего к мейнстриму эта штука: https://vibed.org/

Кхм, Haskell меня нисколько не пугает. А вот то, что вы пытаетесь тут всунуть какой-то сырой фреймворк, разработка которого зачахла года 4 назад так и не дойдя до стабильной версии, выглядит неумно.

Если вы про версию 0.9.5, то она "зачахла" в прошлом месяце. 0.9.4 вполне стабильна. Ну а что лично вас пугает или нет не имеет значения, мы не о вас говорили. А глупо - делать вид, что не знаете о разных подходах к версионированию у разных проектов, и объявлять сырым проект, не требующий ежедневных заплаток.

Вы, видимо, веткой изначально ошиблись, т.к. Haskell предлагали мне. А вы с чего то решили пованговать что я видел, а что нет.

Под "зачахла" я подразумеваю, что активность коммитов существенно снизилась, см. график по ссылке, продублирую вам её: https://github.com/vibe-d/vibe.d/graphs/contributors

Ну, и вы всерьёз считаете активным проект, у которого между версиями 0.9.4 и 0.9.5 проходит примерно год? А 384 issues намекают, что стабильность весьма условна. На половину из них даже никакого ответа нет, что на практике, скорее всего, значит что нет ни одного человека, который занимается поддержкой этого проекта за зарплату.

Не ошибся. Это ветка "что бы посоветовать человеку вместо го". Не будьте таким эгоцентричным.

Ну и гадать по графикам вы не умеете. До середины 2018 шла активная работа над двумя мажорными версиями 0.7 и 0.8. В середине 2018 развитие седьмой версии было завершено.

Проект над которым продолжают работу - активен. Зрелому проекту частые релизы ни к чему. Всего 384 issues только 16 из которых - баги, что весьма не плохой результат. Ну а на зарплате там никто не сидит, да.

Блин, чувак, пиши себе на D, никто ж тебе не запрещает.

Но нафига ты влез в ветку сравнения Elixir c Haskell, которые оба уже много лет имеют веб-фреймворки, до которых vibe.d как до луны что по фичам, что по стабильности (88 issues у Yesod и 26 у Phoenix). А ты пытаешься нас убедить, что 384 - это мало. Нет, это over дохера для веб-фреймворка. Ладно бы это только цифра была, ты зайди на Github, посмотри, что по большинству issues никакого обсуждения нет, им даже не присвоены никакие метки. С таким подходом к разработке кол-во issues будет только расти год от года и сколько там среди них багов никто не знает, потому что их никто тупо даже не читает. Что это, если не заброшенность?

Зрелому проекту частые релизы ни к чему.

Зрелому то да, только vibe.d до зрелости пока не добрался. Где пруфы, что авторы принципиально не планируют версию 1.0? На их сайте я такого тезиса не увидел. Или вы просто выдаёте желаемое за действительное?

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

Овердохера - это 5к ишьюсов у GHC против 3к у DMD. И что? Да ничего. Тоже мне гадание по гитхабу.

Во-первых, некорректно с темы фреймворков на тему самих языков перепрыгивать.

А во-вторых, с каждым коментом ты закапываешь D всё глубже и глубже. Я интереса ради зашёл в их багзиллу 🤦🏻‍♂️
И что я вижу: 4719 issues found. Видимо, с тех пор как ты заходил в issues tracker своего любимого ЯП, он успел ещё почти 2k issues набрать.

И чего ты сравниваешь с GHC, который себя как исследовательский проект позиционирует? Или ты посмотрел на Elixir с его 26 issues и обосрался от зависти? xD
Можешь даже 249 issues от Erlang/OTP приплюсовать.
А то вы со своим D даже хипстерский Crystal в 4 раза по кол-ву issues обогнали.

Просто у Дмитрия склонность форсить проекты, которые "не взлетели". К слову сказать, действительно интересные, классные технологии. Но, к сожалению, нужные 2,5 энтузиастам :)

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

Прошу меня извинить, что я влез в ветку сравнения Elixir c Haskell.

Ну а какой смысл рассказывать людям про проекты, которые "взлетели"? Они и так про них знают. Каждый раз, когда я вижу очередное нытьё про Go или C++, React или Angular, мне становится грустно от того, сколько времени люди убивают на бестолковые решения, вместо того, чтобы вложить его с большей пользой для "взлёта" чего-то, что может вытянуть индустрию из этого болота.

UFO just landed and posted this here

В этом я могу вас понять. Но D, к сожалению, закопали сами разработчики, сначала расколов и так небольшое комьюнити на Phobos и Tango прям аккурат в момент релиза 1.0. А потом и полгода не прошло, как бросились вторую мажорную версию языка пилить. В довершение ко всему этому ещё и не уловили тренд на OpenSource. Тем самым отложив интеграцию с gcc лет на 10.

А программисту хочется хотя бы иметь ощущение, что авторы ЯП понимают, что они делают, и придерживаются хоть какой-то генеральной линии. Возможно, в этом и причина популярности Go. Да, генеральная линия его разработчиков - треш и угар, но они неукоснительно её придерживались, как минимум, 8 лет.

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

Да-да, у го прекрасная интеграция с гцц

Тем не менее, через 3 месяца после выхода Go 1.0 она уже была. А сколько лет с релиза D 1.0 прошло до включения в GCC?

а дженерики не раскалывают сообщество

Потенциально раскалывают. Но языку уже 10 лет, теперь он может себе позволить хоть несовместимую версию 2.0 выпустить, это уже не сильно заафектит его популярность.

Всё, что вы перечислили, на популярность не влияет вообще.

Поделитесь тогда своим мнением почему D настолько непопулярен?

А чего Cloud Haskell до стабильной версии не дотащили и забросили?
Не нравится мне shared memory, даже под соусом STM.

Так то мне многие идеи Haskell импонируют, но OTP - это прям самое мощное и самое подходящее, что я видел, для веб-разработки среди порядка 20 ЯП.

Под BEAM, кстати, появился ML-подобный язык, в активной разработке сейчас: Gleam. Как автор признаётся, он хотел его сделать похожим на Haskell, но из-за негативной обратной связи отказался от этой затеи.

UFO just landed and posted this here

Жаль. Строго типизированные акторы были бы интересны. Но это, наверно, на уровне самого языка надо делать, т.к. объём работ большой и авторы отдельной библиотеки на одном энтузиазме далеко не уедут.

Мимопроходил - а Akka Typed в скале - это не те самые строго типизированные акторы?

Да, они. Но к JVM у меня какая-то личная неприязнь. Всё, что я на ней видел, имело медленный старт и дико жрало память.

Возможно, в Akka.NET тоже что-то подобное есть, но до F# я пока не добрался)

UFO just landed and posted this here

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

Я вообще за минимальный и тупой язык

Как же вы с Haskell уживаетесь? Я бы не назвал его ни минималистичным, ни тупым.

Лично мне распределённый STM больше понравился. 

По-моему, DSTM, как и CloudHaskell, тоже давно заброшен.

UFO just landed and posted this here

А можно несколько примеров этих альтернатив?

UFO just landed and posted this here

Слышал, что Idris "исправляет" какие-то моменты в хаскеле, но он ещё и минималистичный и расширяемый?.. А есть шансы, что он начнёт теснить хаскель? Или преимущества не настолько большие, чтобы перевесить отсутствие библиотек и инфраструктуры?


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

UFO just landed and posted this here
Новый ЯП не хотите сделать (без прикола)? Чтобы простой ЯП + библиотеки из Haskell/Scala/F#/etc?
UFO just landed and posted this here

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

UFO just landed and posted this here

Я бы сказал, что это либо про коммьюнити из этак 2005

Телега на самом деле не моя, но программистов которые пытались вкатиться в функциональщину. Обычно самым большим минусом зовут консерватизм/элитаризм языка ("в 1970е уже все изобрели") и закидывание шапками за отсутствие знаний из теорката и прочих смежных дисциплин.

Prelude, с одной стороны, действительно стрёмный

опять же я не столько за стандартные библиотеки, сколько за УДОБНЫЕ инструменты каким стал cargo у Rust. Сборка, управление пакетами, всякие флаги оптимизации, подпись/публикация пакетов и куча прочего по большому счету не связанного непосредственно с кодом - все из одного места и без большой боли. Опять же я на настолько функциональных языках, как Haskell, длиннее Hello world не писал, поэтому по большей части ссылаюсь на опыт других людей и допускаю, что не так плох чёрт, как его малюют.

UFO just landed and posted this here

Могу предложить вам попробовать Elixir. Сообщество дружелюбное, теоркат знать не требуют, инструментарий удобный: iex, mix, hex.

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

UFO just landed and posted this here

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

UFO just landed and posted this here

Мне после опыта коммерческого программирования на ширпотребе и хоббийного на Хаскеле первая книга была прям откровением "а чё, так можно было?!"

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

Больше похоже "на вот пять спорных недостатков - давайте к нам в rust". При этом не приводится даже как же эти недостатки в rust решены.

Нет там никакого "давайте к нам в Rust", вы это сами себе придумали. :)

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

Звучит как-то неконкретно. Можно пару примеров?

Мутабельность данных, от которой нельзя избавиться - ключевые слова final, const и иже с ними (val/var) есть давно в примерно каждом языке, на котором я писал и который я помню.

Неумение разделять данные и ошибки, данные и отсутствие данных - всякие там "монады" (на самом деле не во всех языках они реализованы стандартно как честные монады - например, джавовый Optional монадические законы нарушает) Optional/Maybe/Try.

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

В golang есть const. Почему вы и автор статьи вдруг решили что нет? Я встречал исключения java которые отправлялись по почте программисту. Там было 500 Mb текста (просто обернул try все приложение tomcat). Естественно это письмо ему не пришло. Это точно лучший способ обрабатывать ошибки? Был еще такой вариант try, а результат игнорируем. При этом я часто встречал, как на обработку ошибок забивали совсем. К примеру дергаем какую-нибудь функцию из winapi(у которой есть задокументированное возвращаемое сообщение об ошибке) и не обрабатываем ошибку совсем. Потом приходим и делаем мозги сисадмину, как же так - почта не отправляется. Смотрю в логи: а на почтовый сервер никто даже не постучался. По мне так в go не так уж плохо с ошибками, если есть возвращаемая ошибка, то ее нужно явно проигнорировать, либо не обрабатывать никаких возвратов из функции совсем. Есть еще вариант "собирался обработать, но забыл". Но для страховки от таких ошибок сейчас есть инструменты.

Опять же. Сейчас в принципе можно программировать на go в режиме "java-программиста": просто на каждую ошибку вызываем panic и log.Fatal, а в main recover и циклическая перезагрузка приложения, но зачем?

В golang есть const

...который позволяет использовать только compile-time константные литералы:

Constants can be character, string, boolean, or numeric values.

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

Там было 500 Mb текста (просто обернул try все приложение tomcat)

Да, это какой-то абсурдный эдж-кейс, пример чьей-то некомпетентности. Но встречающееся в бОльшей части увиденного мной го-кода data, err := someCall(); if err != nil { return nil, err}лучше только неабсурдностью, практическая полезность всё ещё нулевая.

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

..который позволяет использовать только compile-time константные литералы:

А в c и с++ это по-другому?

Но встречающееся в бОльшей части увиденного мной го-кода data, err := someCall(); if err != nil { return nil, err}лучше только неабсурдностью, практическая полезность всё ещё нулевая.


что вам не нравится в приведенном вам примере? Ошибка не проигнорирована. Она обработана, просто программист решил ничего от себя не добавлять. Может там это и не требуется. Если бы вызвал fmt.Errorf и добавил бы что делал когда ошибка вылезла, было бы лучше? если что там можно указать файл и строку откуда это вызвано, только всегда ли нужно?

Кстати возможно вы имели в виду
if data, err := someCall(); err != nil { return nil, err}

Тогда да. data никогда не будет обработан, err только в случае ошибки, но err = nil никому и не нужен. Но такую ошибку может только новичек совершить, и то, тот что невнимательно вводный курс прошел на сайте.

UFO just landed and posted this here

Go с самого начала наследовал именно синтаксис этих языков с поправкой на упрощение синтаксиса и форматирования.
Динозавры. Так где там rust/python/java/c# для микроконтроллеров? Почему ардуинщики на них не пишут? Почему когда речь заходит про java или micropython, то там речь про ну вот мы написали обвязку вокруг сишного SDK. А где реальные "дрова" оборудования на rust? А чего это никто еще c++ api из windows до сих пор не выкинул и не заменил на .net?
Вот буквально вчера работал в MPLABIDE. И представляешь, там реализация switch на c для микоконтроллеров PIC18 отсутствует.

UFO just landed and posted this here

Rust для микроконтролеров вполне используется.

Не затруднит показать хоть один реальный проект где не мигают светодиодом и не используют spi/i2c. А что нибудь где например используются прерывания и сон устройства. Короче покажите проект на rust(без использования родного SDK) который использует возможности хотя бы одного контроллера на 100 % gpio/i2c/adc/dac/spi/interrupts/sleep/etc. Потому что фреймворков умеющих мигать светодиодом я видел сотни. А вот когда дело касается реальнызх проектов, то увы и ах.

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

UFO just landed and posted this here
UFO just landed and posted this here

Так SDK написанный, как правило, на c - это все, что способен выполнить ваш код <на современном ЯП>. Т. е. единственная его функция вызвать код на С, а дальше зона ответственности заканчивается, т.е. вы запустили rust, который вроде безопасен, но вся безопасность заканчивается на реализации кода на С за который вы не отвечаете, если там в коде кто-то выудит ваши секреты, вы же не отвечаете? Потому моё отношение такое. Хотите доказать, что ваш язык современен, производителен и безопасен - вперед. Спецификции большинства процессоров со всей периферией давно в широком доступе, но что-то не вижу я распространения таковых в широком доступе, вроде бы есть одна ОС на чистом rust, но и у той распространенность и поддержка железа уступает reaсt os. Равно как и существуют прототипы ОС на go. Черт, я даже драйвер для dht-22 на raspberry pi на go написал. Но утверждать, что за rust или go будущее не берусь. Слишком много "перспективных" языков было похоронено за последние 20 лет.

UFO just landed and posted this here

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

До нее были Delphi/Pascal.

UFO just landed and posted this here

В свое время (середина нулевых) да. Я вот помню, как многие производители писали консоли управления raid-контроллерами на java, телефоны поддерживающие приложения на javame. Чуть позже телефоны отпали. там появились приложения на c/c++ для windows mobile и symbian, но java me долгое время поддерживали устаревшие промышленные GSM модемы и некоторые станки с ЧПУ. Консоли raid-контроллеров кстати тоже очень быстро вернулись на c++.

А, ну и андроид к чему изначально тяготел и был буквально привязан? К java.

UFO just landed and posted this here

Android. Я может удивлю, но в свое время некоторые драйверы вполне себе на java писали. Особенно касалось всяких там USB-токенов или весов, или каких-нибудь фискальных регистраторов. Та что там, и прототипы ОС на java были. Так что ничто не ново.

Опять же, что такое консоль управления RAID-контроллером. По большей части это конечно инфа в web-интерфейсе, но есть драйвер и ряд прямых команд этому драйверу вызывающих например создание или перестройку массива, и все это точно работало не через web-api.

UFO just landed and posted this here

Т. е. как любой java - код опираясь на java VM?

UFO just landed and posted this here

 rust/python/java/c# для микроконтроллеров

за трех последних не скажу, но у раст embed/bare metal есть и цветёт полным цветом. Даже на хабре писали, не говоря уже про официальный шоукейс. Про дрова в статье уже написал - блютус стек андроида, аналогично у Fuchsia, в Линуксе пока на котиках эксперементируют, поэтому в мейнстриме окисленного кода пока нет, хотя Линус уже грозился в следующей версии выпустить немного. На одной из конференций один чувак выступал с рассказом как они ту же ржавчину для спутникового ПО использовали.

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

А в c и с++ это по-другому?

В D определённо по другому.

 там можно указать файл и строку откуда это вызвано, только всегда ли нужно?

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

UFO just landed and posted this here

Не вижу с этим проблем. Просто ссылка на отладочную информацию будет в нескольких местах.

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

А теперь представьте, что не вы один на проекте, а проект не Hello World, а код писали вообще не вы.

Ну да, вы всегда можете руками написать свой кривой стектрейс.

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

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

У вас либо предвзятость подтверждения, либо телепатия. Всем остальным сообщение "не могу прочитать такой-то файл" ничего не говорит о том, где и почему был вызов того кода, который привёл к вызову другого кода, который обратился к читалке конфига, один из методов которой и упал.

Т. е. мысль о том что код на go достаточно легко читается и отслеживается, что отследить сообщение об ошибке до источника не большая проблема вам в голову не приходит?
Это же простой язык тут не бывает как в с++:

void begin(const char* hostname, uint16_t port)
...
void begin(IPAddress ip, uint16_t port)

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

Вы предлагаете глазками что ли вычитывать кто кого где и почему вызывает?

UFO just landed and posted this here

Так я уже указал. Двух функций с одинаковым именем быть не может. Так что достаточно найти собщение об ошибке, а дальше тех кто его выводит. Если это не твой код, то там как правило сообщения уникальные, тебе остается пронумервать все точки, где это сообщение выводит твой код. Случаи, где return err мне попадаются достаточно редко(как правило это я сам, так я и не делюсь кодом по причине того, что стыдно). Если что-то выкладываю, то стараюсь чтобы там было все обработано.

Что, и имена методов тоже все уникальные для всех объектов?

В го же нет методов и объектов в привычном понимании адептов ООП. Но да, для одного "объекта" не может быть двух методов с одним именем. Т. е. будет:

OpenbyHostname(hn string)
....
OpenbyIP(ip net.IP)

вместо

Open(hn string)
....
Open(ip net.IP)

Речь про разные объекты. Не делайте вид будто не понимаете.

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

Всё нормально. Не вижу с этим проблем.

Ухудшение читаемости и засорение пространства имён, как по мне. Заставляют дублировать в имени функции то, что прекрасно демонстрируется типом её аргумента.

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

Constants can be character, string, boolean, or numeric values.

Какого стандартного типа go тут не хватает. struct? А точно в c struct может быть константой? И часто встречаются константы такого типа?

Ну так ключевое слово const к константам никакого отношения не имеет, так уж сложилось исторически.

UFO just landed and posted this here

В с ваш пример не компилируется. в С++ работает, но есть ньюанс "не константа, а read-only variable" , тогда так https://stackoverflow.com/questions/47632706/immutable-struct-in-golang

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

Таким образом. Все чего яко-бы нет в <язык программирования> на самом деле есть, но как правило делается способом отличным от того, что имел в виду <автор утверждения>, и от того ему лично неудобным. Это кстати относится к любому срачу: Windows vs Linux, MSO vs LO etc.

UFO just landed and posted this here

GCC 12, да но 10 уже нет.

<source>: In function 'main':
<source>:1:20: error: parameter name omitted
    1 | int main(int argc, char**)
      |                    ^~~~~~
Compiler returned: 1

UFO just landed and posted this here

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

Развести горы копипасты вместо написания одного слова immutable - очень по гошному, да.

Вы же понимаете, что с подобным подходом вы создаете богатую почву для критики любого ЯП?
Развести горы копипасты для <действия>, которое я у себя делаю в два клика.
Например в go мне не нужно начинать Hello World с создания класса или объявления namespaces как в C#. Я же не заявляю что шарперы развели копипасту.

Есть не большая разница между "плюс 2 строки" и "в 2 раза больше строк".

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

Вроде обязательное форматирование табами столько места не занимает.

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

Так все просто. Просто создаем структуру и указатель, но не создаем методов способных изменить структуру, только чтение. Или что, опять длинно?

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

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

Вам язык явно мешает это делать. Костылями мы все умеем пользоваться. Самыми разными.

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

Ага 100500 одинаковых методов для чтения значений, прекрасно.

В Джаву завезли специальную языковую конструкцию чтобы дать возможность делать сложные иммутабельные объекты. Которые естественно можно инициализировать чем угодно.

Ну да, кому они нужны?

в какой-то из новых версий шарпа (вроде .NET 6.0) это не требуется. специально для hello-world-проектов завезли, можно не указывать класс и неймспейс. подставит по умолчанию.

UFO just landed and posted this here

А нужно? Для этого есть более подходящий язык? Т. е. на go или любом другом языке можно решить конкретную задачу в особо упоротых случаях можно вызвать c или asm, но язык все так же остается инструментом для решения конкретной задачи.

Я отвечу почему я им занимаюсь.
1. Простой. Я не профессиональный программист пришел к go когда для моих задач(системное администрирование/DBA, windows + linux стало не хватать обычных скриптовых языков вроде cmd/sh/bash).
2.Когда понадобилось копировать по сети за пределами os.copy
3. Когда понадобилось копирование множества файлов одновременно.
4. Когда понадобилось запускать свой код на компах где нет нужного рантайма(Можно на .net,вот только тогда еще .net не работал под linux. И у меня был зоопарк систем от windows NT 4.0 до windows 2012, и от centos5 до debian8)
5. когда потребовалось за короткий срок написать tcp-сервер принимающий множество сообщений одновременно.

6. Когда понадобилось сделать парсер для KX-TDA200 c составлением отчета о звонках.

7. А дальше пошло-поехало Modbus-устройства, расширение modbus-tcp, реверсивный modbus и мосты к сторонним системам, modbus over GSM....

8. А теперь все то же но на Arm....

UFO just landed and posted this here

А в чём проблема? Пишете return, join, и вперёд. Руководств по монадам на Go предостаточно.

UFO just landed and posted this here

что вам не нравится в приведенном вам примере? Ошибка не проигнорирована. Она обработана

Ну тогда джавист из вашей истории, обернувший всё тело программы в трай-кэтч, тоже обработал ошибку, чо. Тоже сделал rethrow.

  • Проверяемые компилятором исключения в Java.

  • Контроль мутабельности, чистоты и потокобезопасности компилятором в D.

checked exceptions в джаве кстати как раз одно из спорных и непопулярных решений. Другой вопрос, что даже оно лучше, чем то, что наворотили в го.

А что там спорного? Хомячкам говнокодить не даёт?

try-catch-based логика отвратительно читается, хуже тестируется и вообще более error-prone в моих глазах, чем более "чистые" в смысле флоу кода механизмы возврата и обработки ошибок. А ещё есть очень много откровенно unrecoverable ситуаций.

Чуть более развёрнуто есть тут, например.

try-catch-based логика отвратительно читается

Не хуже чем if, switch, for и тд. Претензию тут можно предъявить разве что к тому, что во многих языках зачем-то сделали, что переменные, объявленные в try не доступны в catch.

хуже тестируется

Это о чём вообще?

 более "чистые" в смысле флоу кода механизмы возврата и обработки ошибок.

Речь про монады? Вот уж что действительно плохо читается, так это возня с монадами. Не даром в том же расте появился макрос try, а потом и просто вопросик означающий, что "тут может вылететь птичка" будто где-то она вылететь не может.

 А ещё есть очень много откровенно unrecoverable ситуаций.

Восстанавливаемые они или нет решать уж точно не в месте их возникновения.

UFO just landed and posted this here

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

UFO just landed and posted this here

У ифа, свитча, фора, и прочих куда более очевидная логика перехода/ветвления, чем у try-catch. У них это "проверь условие на входе - неверно - иди в другой блок [и проверь условие там, если надо]". У try-catch это "видишь вот этот блок и абсолютно всё, что в нём вызывается? В любой момент абсолютно что угодно из блока этого может сделать плохую магию, и ты перескочишь вот в один из тех других блоков" (кэтчей-то бывает несколько).

А ещё если у трая большое тело, контекст теряется только в путь.

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

Альтернативные решения таким, как правило, не страдают.

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

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

либо будет ожидаемый переход в catch

В какой момент кода и в каком состоянии системы он произойдёт? :)

Тестировать надо поведение, а не строки.

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

Не поверите, в случае любой исключительной ситуации.

Зачем вы проверяете поведение зависимостей? Что вы будете делать, когда зависимость поменяется? Будете переписывать все тесты?

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

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

UFO just landed and posted this here

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

UFO just landed and posted this here
То, что в текущей реализации checked exceptions не решают возложенные на них задачи, но при этом заставляют программиста делать кучу приседаний, которые так-то ему не особо и нужны.

Давайте посмотрим на классику — интерфейс Readable из JDK

int read(CharBuffer cb)
throws IOException

Throws:
IOException — if an I/O error occurs
NullPointerException — if cb is null
ReadOnlyBufferException — if cb is a read only buffer


Заставляет ли джава обработать все ошибочные сценарии? Нет, ей наплевать на ReadOnlyBufferException. Заставит ли меня каждый вызов оборачивать в try/catch? Да, хотя вызывающему коду в 90% случаев вообще наплевать, что там сломалось — не смог прочитать и не смог, залоггировал и дальше поехали (при этом язык никак не мешает хомячкам бахать пустой catch и съедать исключения).

Если вам мало — можете заглянуть в класс Cipher. Там вообще красота

public final int doFinal(byte[] output,
int outputOffset)
throws IllegalBlockSizeException,
ShortBufferException,
BadPaddingException


Note: if any exception is thrown, this cipher object may need to be reset before it can be used again.

Throws:
IllegalStateException — if this cipher is in a wrong state (e.g., has not been initialized)
IllegalBlockSizeException — if this cipher is a block cipher, no padding has been requested (only in encryption mode), and the total input length of the data processed by this cipher is not a multiple of block size; or if this encryption algorithm is unable to process the input data provided.
ShortBufferException — if the given output buffer is too small to hold the result
BadPaddingException — if this cipher is in decryption mode, and (un)padding has been requested, but the decrypted data is not bounded by the appropriate padding bytes
AEADBadTagException — if this cipher is decrypting in an AEAD mode (such as GCM/CCM), and the received authentication tag does not match the calculated value


Три проверяемых исключения, которые в 90% случаев бесполезны, и еще 2, которые всё равно уронят весь код, если вы их не обработаете руками, и которые так же бесполезны.

Заставляет ли джава обработать все ошибочные сценарии? Нет

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

Заставит ли меня каждый вызов оборачивать в try/catch? Да

Не врите.

не смог прочитать и не смог, залоггировал и дальше поехали

if в данном случае ничем принципиально от try-catch не отличается.

Три проверяемых исключения, которые в 90% случаев бесполезны,

Их хорошо бы объединить в CipherExceotion.

и еще 2, которые всё равно уронят весь код

Ну так, лучше бы выпилили UnchekedException вообще.

Заставлять она и не должна.

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

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

Судя по приведенным выдержкам из джавадоков с этой задачей с этой задачей справляются, кхм, джавадоки. Если мне нужно понять, какая может вылететь птичка — я смотрю в них, потому что может быть и unchecked exception, который мне всё равно не мешало бы обработать.

Не врите.

NO U.

Ну так, лучше бы выпилили UnchekedException вообще.

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

Не пытается и не заставляет. Чего вы фантазируете?

Джавадоки не проверяются компилятором.

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

Не пытается и не заставляет. Чего вы фантазируете?

class Scratch {
    public static void main(String[] args) {
        ByteArrayInputStream stream = new ByteArrayInputStream(new byte[] { 1 });
        stream.close(); // unreported exception java.io.IOException; must be caught or declared to be thrown
    }
}

Или вы мне сейчас попытаетесь сказать, что ошибка компиляции — это «уведомить»?

Джавадоки не проверяются компилятором.

Вы начинаете понимать суть проблемы.

Ага, круглые колёса — это плохо

В том и дело, что они не круглые, а полукруглые.

Ну и где тут обёртка?


class Scratch {
    public static void main(String[] args) throws IOException {
        ByteArrayInputStream stream = new ByteArrayInputStream(new byte[] { 1 });
        stream.close();
    }
}
Плохих языков не бывает

Бывает, ещё как бывает. C — плохой язык. C++ — плохой язык. Go — плохой язык. 1С, прости г-пди — плохой язык.

UFO just landed and posted this here

Солидарен с Дедфудом: хороших нету, есть лишь менее плохие.

Для контроллеров на чём писать? Если не С то что?
Я имею ввиду 8 битники. AVR, PIC и прочее. Там чуть ли не на асме надо писать
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here

Есть uTCP. Туда вообще умельцы много чего помещают. Например, виртуальную lisp-машину с реализацией http-сервера поверх неё.

Я когда то писал TCP/IP стек на С. Даже писал ещё ниже уровень PPP А только поверх него уже IP и далее TCP. Было очень давно, подробностей не помню, но кода получилось довольно мало. Это было во времена первых GPRS модемов. В жирный AVR уместилось бы. Конечно вероятно не все ситуации код мог переварить, но минимальный рабочий вариант получился. Там не так страшно — пришедший пакет упакован как матрёшка из данных. Просто надо найти адреса последовательно где какой протокол начинается и добраться до данных. Сами пакеты TCP/IP примитивны и просты.
UFO just landed and posted this here
Ну контроллеры ставят во всякие железячные устройства. Лампочкой поморгать или ещё чего. Или наоборот — отослать сигнал. Там и требуется только например по GPRS отослать на какой нибудь IP булеву переменную, что у тебя например огурцы на даче поливать надо ))) Хотя сейчас например даже в самом захудалом GSM модеме свой TCP стек.

Если контроллер только для передачи сигнала через net — то там нечего ломать. А если на приём. То я не сильно представляю где голый контроллер может в сеть смотреть. Это либо всякие свичи и модемы для оптики или ещё что. У всего этого как правило есть свои настраиваемые фаерволы или криптотунели.

P.S. Сначала написал комент про лампочку, а потом прочитал ваш ))) Короче все думают про лампочку ))) А Выбор AVR или там STM32 — только в цене по мойму. Берут что подешевле. Хотя STM раньше стоил дешевле AVR — что меня очень удивляло. Сейчас не знаю как.
Он же не будет торчать в открытый интернет

зато всякие неожиданные значения на входах — обычное дело

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

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

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

кто всем сердцем соглашаются с моей филиппикой

Здесь подразумевается монета? Или опечатка?

В Go нет тип-сумм — и поэтому там реально неудобно написать тип, который представлял бы «либо адрес IPv4, либо адрес IPv6

В большинстве случаев такое спокойно решается через type switch. Но тут, думаю, нужно изначально проектировать по-иному — напр. работать не с конкретными типами, а с интерфейсами, и тогда без разницы что под капотом — ipv4, ipv6 или номер квартиры.


нo не допускает перегрузки операторов, напоминая о той давней истории Java, когда a == b не было идентично a.equals(b)

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


В Go отсутствует поддержка неизменяемых данных. 

По старинке — обернуть в read-only интерфейсы. Вообще мне больше импонирует идея view-интерфейсов, т.к. они более гибкие, чем какой-то один прибитый гвоздями механизм на уровне языка.


В целом я бы сказал, что для 90% случаев существующие примитивы — good enough. В 10% случаев нужны танцы с бубном. В каких-то языках из-за перфекционизма танцы с бубном будут больше 10%, зато всё теоретически красиво. Всё-таки, Go замышлялся как простой язык.

Всё-таки, Go замышлялся как простой язык.

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

Первый же пример абсолютно нелеп и притянут за уши -- Го серверный язык и работа с файловыми атрибутами на винде ему нужна как собаке пятая нога. И что мы видим как контрпример? Естественно, раст! Опять же, без комментариев. Само собой, это просто объективная критика Го, а никакая не попытка пропихнуть Раст. Да, всё так.

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

  • Тогда можно а) не поддерживать Windows б) не поддерживать соответствующие файловые системы

  • "Го серверный язык" где написано? На оф.сайте го не вижу ни слова о том, что на винде его запускать нельзя или не нужно (более того, я сам в продакшн код на го из-под винды писал).

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

Я прочитал первую статью ещё когда она вышла, а вторая только укрепила моё мнение относительно автора и его мотиваций. Заглянул тут ещё ради смеха на ютуб канал автора -- раст, раст, раст. Один сплошной раст. Для меня всё очевидно как божий день. Но если кто-то верит в то, что автор просто вдруг на ровном месте решил pro bono покритиковать Го, это его дело.

А почему в русскоязычном комьюнити так оголотело не любят раст? Есть какая-то фундаментальная причина или это просто технологическое отставание от запада?

Это вопрос к сообществу, а я обсуждаю конкретную статью, где под видом критики Го я вижу пропихивание Раста. Вот за такое, очевидно, и не любят.

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

Специфическое отношение у кого? У вас лично?

Нигде никакого массового "специфического отношения" к расту я не видел.

Далеко ходить не надо: https://www.google.com/search?q=why+people+hate+rust

А теперь подставьте туда java, javascript, php, python и go (golang к сожалению недостаточно распространённое название - а зря).

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

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

При чём тут гугл? 

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

Эта ссылка была просто для примера

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

И даже эта статья, которая вроде бы должна была быть о Го, превратилась в срач о расте.

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

UFO just landed and posted this here

если кто-то верит в то, что автор просто вдруг на ровном месте решил pro bono покритиковать Го

Не "на ровном месте", а (как написано в статьях) потому что он активно на нём писал - в том числе на работе - и пытался с ним "подружиться".

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

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

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

Ну вот про файлы, chmod и Windows это прям... не уникальная проблема.

Вот к примеру боль автора питоновского модуля oschmod:

Even though Python's os.chmod() sets read, write, and execute file permissions, on Windows, os.chmod() basically has no effect. Even worse, Python on Windows gives no warnings or errors. If you think you set file permissions on Windows with os.chmod(), you're wrong!

Ну то есть буквально в Go скопировали поведение Python.

Хорошо ли это? Нет, могли бы и нормально сделать.

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

Стоило ли из-за этого "не поддерживать Windows"? Нет. По крайней мере ровно в той степени, в которой тогда надо "не поддерживать Windows" в Python. Остальное то (наверное) работает. Nice небось тоже на Windows кривой почти везде и молча делает ничего, но ничего, пока никто не расстроился.

Ну да, я не питонист.

Хорошо ли это? Нет, могли бы и нормально сделать.

Ага, всё так.

Можно ли это понять? Да, можно

Нет, не можно, когда вы делаете строго типизированный язык (я тут могу много материться по поводу interface {}, но язык всё-таки строго типизированный) в конце нулевых, когда, помимо другого подхода к типизации, мир и концепции дизайна ЯП несколько отличаются от тех, в реалиях которых Гвидо дизайнил Пайтон или даже тех, в которых он довыпускал Python 2.2, в котором появился chmod.

Нет, не можно, когда вы делаете строго типизированный язык

Так а причем тут строго типизированный язык, если я говорю об одном конкретном наезде про chmod?

Наговнокодить в кросс-платформенной реализации чего либо достаточно просто. Особенно если эта платформа не является целевой. В целом странно ожидать, что chmod будет работать в windows, где в принципе нет битовой маски свойств, правда? Но наверно ошибочку таки стоило бы писать.

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


Если бы пакет, предоставляющий Chmod, назывался бы не "os", а "os.unix" или "os.linux" — претензий бы к нему было меньше.

Если не лениться читать, то в описании пакета os в Go написано следующее:

Package os provides a platform-independent interface to operating system functionality. The design is Unix-like, although the error handling is Go-like; failing calls return values of type error rather than error numbers. Often, more information is available within the error. For example, if a call that takes a file name fails, such as Open or Stat, the error will include the failing file name when printed and will be of type *PathError, which may be unpacked for more information.

The os interface is intended to be uniform across all operating systems. Features not generally available appear in the system-specific package syscall.

The os interface is intended to be uniform across all operating systems. Features not generally available appear in the system-specific package syscall.

Установка прав доступа через битовую маску — это и есть та самая "feature not generally available", но в os она таки почему-то есть.

Тут дилемма — если наваять most common denominator, т.е. только те фичи, которые есть во всех OS, то API работы с окружением будет ограничено в фичах, от этого страдала Java, например. Другой вариант вообще не делать общего API, но тогда из коробки вообще ничего нет. Выбор Unix-поведения как дефолтного считаю на практике обоснованным, т.к. целевая аудитория Go это всё-таки Unix-подобные системы, которых большинство, и Windows тут скорее исключение, чем правило. Такова реальность — в итоге в самом Windows добавили WSL, posix compatibility layer; инструменты разработчика портируются с Linux на Windows, и не наоборот.

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

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


Тут, думаю, нужно впервую очередь смотреть на практику. В целом, на Go довольно просто писать код. Но доказать, что код корректный, сложнее, чем, например, в Rust. И тут мы упираемся в то, что по большому счёту все холивары основываются на субъективных ощущениях, интуиции. Очень мало у нас опираются на исследования и метрики по поводу того, как та или иная фича влияет на разработку. А иначе мы просто топчемся на месте. Недавно открыл для себя термин evidence-based software engineering, по нему есть литература, напр. одноимённая книга Дерека Джонса.

В целом, на Go довольно просто писать код.

Ну вот в том и дело, что автор статьи (как и я) писал на Го код профессионально довольно продолжительное время, и пришёл к совсем другим выводам. Я с автором в этом согласен.

UFO just landed and posted this here

Только в Марте этого года (а ему сколько уже, 12 лет?) в Go добавили generics и этим все сказано.

Для тех кто не работал с Go, а что все сказано? Прошу кэпа на помощь. То что изначально авторы языка говорили дженериков и шаблонов не будет, а теперь сдались? Типа он уже никакой не минималистичный и простой? Или типа вот только в марте добавили, поэтому все посты про то что в Go нет нормальных возможностей уже надо закапывать? Я не особо понимаю как это конфликтует с оригинальной статьёй.
Эм? я знаю что такое generics, вопрос не в этом. что «этим всё сказано».

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

Нет, не знаю. Просвятите? Вы и правда считаете, что я от нечего делать спрашиваю о том, что знаю сам? Смысл какой?

То есть вы не знаете, что такое обобщённое программирование. Узнать о нём вы можете по ссылке выше.

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

Давайте сначала. Я C++ разработчик. GP я вполне себе на каком-то уровне уменю в этом языке.
Я читал новость о том что в Go добавили generic-и, выглядит как что-то (на совсем поверхностный взгляд незнакомого с Go) позволяющее работать в GP парадигме. Насколько это соответствует мощи шаблонов С++ — не берусь сказать. Возможно, не соответствует. В любом случае что
а) в Go все нормально сейчас с GP
б) или в Go добавили generics но их сильно мало
я все еще не понимаю, как эта информация что их уже добавили в этом году соотносится с «этим все сказано», с какой частью статьи это коррелирует.

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

Суть в том, что авторы языка принципиально не хотели вводить generic-и в Go, призывая сообщество к говно-решению вопроса (писать кучу boilerplate-кода). Теперь generic-и добавили, но догадайтесь сколько говнокода уже написано за эти годы и сколько лет понадобится, чтобы исправить ситуацию.

Это миф про то, что "принципиально" не хотели. Если поискать через wayback machine, то официальный faq уже в 2013 году (раньше не нашёл) писал о том, что они открыты к добавлению дженериков, но пока нет понимания, как лучше реализовать.

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

Авторы создали Go, потому что устали ждать долгой компиляции проектов на C++ в проектах Google. Изначальная идея Go была в том, чтобы это был простой good enough язык, который легко масштабируется на большие кодовые базы at scale и при этом быстро компилируется. По сути основные первоначальные решения отталкивались именно от этого — быстрая компиляция больших проектов (что иронично, когда сейчас один из основных use case'ов Go это микросервисы). Отсюда запрещены циклические зависимости, поэтому в язык добавлен structural typing, поэтому нет наследования, поэтому местами синтаксис немного странный — для быстрого парсинга, и т.д. Дженерики, шаблоны — они значительно могут замедлить время компиляции и сильно раздуть код (code bloat), если их неправильно приготовить. Поэтому много времени ушло на то, чтобы найти правильный баланс, т.к. авторы, видимо, были травмированы опытом в C++. Go часто по фичам сравнивают с Rust, но там вроде время компиляции не возведено в абсолют, и я слышал истории, что в Rust со скоростью работы компилятора не так всё гладко. То, что авторы Go в рантайме в итоге реализовали для оптимизации компилятора, похоже на generic code sharing при реификации дженериков в C#, которые там давно есть. Странно, что так долго к этому приходили, возможно были трудно решимые проблемы с семантикой/синтаксисом, чтобы было backward compatible. Т.е. тут основной косяк авторов в том, что первоначальный драфт языка не проектировался с учётом расширения его под дженерики, напр. теперь map[int]int смотрится странно.

Мне, конечно, до авторов Go далеко, но, вот, всё же, зря они пошли на поводу у сообщества. Добавили бы лучше generic functions. И синтаксис такой бы вписался бы лучше в язык, и по выразительности они достаточны, и по производительности хуже не были бы, учитывая текущую реализацию generic-ов.

Всё-таки основной use case дженериков это обобщённые контейнеры. Из-за этого по факту в Go всего два типа контейнеров — слайсы и мапы, что далеко от идеала. Как наличие только generic-функций решило бы этот вопрос?

С++ компилируется долго из-за кривого дизайна, унаследованного от C. Go корректней сравнивать с D, который и компилируется быстро, и дженерики были сразу, а не через 12 лет. И много чего ещё умеет, чего не умеет Go.

Многие хвалят D, но остаётся подвисшим вопрос — почему он не взлетел, если он настолько хорош? Был аргумент, что за ним не стояла большая корпорация, но за последнее время появилось несколько языков вроде Zig, к которым сейчас, субъективно, больше интереса, чем к D. Дело ещё не в языке, а в тулинге например. Может быть, с тулингом что-то не так? В Go много хорошего, что есть из коробки, не касается языка как такового.

почему он не взлетел, если он настолько хорош?

  • Если за холмом трава зеленее, то почему все прыгают с обрыва?

  • Ну все туда бегут и я побежал.

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

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

Я бы не сказал, что чистый Си компилируется медленно. Полчаса для проекта размера ядра Линукс это немного. Плюсы это другой разговор. Так что аргумент про кривой дизайн требует как минимум раскрытия.

Это не кривой. Просто в D лучше, спору нет.

Заново парсить файл в каждом месте его включения - не криво? А что же тогда криво?

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

Это неправда.

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

Дженерики как в джаве сильно нагружают гц и лишают вас возможности нормального дебага в рантайме.

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

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

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

Дженерики как в джаве сильно нагружают гц

Чем, пардон, джавовые дженерики нагружают ГЦ больше, чем любые другие?

лишают вас возможности нормального дебага в рантайме

Во-первых можно делать их reified (хотя кмк это поощряет некоторые сомнительные практики в разработке, но не суть), во-вторых, и с type erasure всё в рантайме прекрасно дебажится.

Дженерики как в плюсах замедляют время компиляции

Ну вот только в плюсах не дженерики, угу. Шаблоны - несколько не то же самое.

Чем, пардон, джавовые дженерики нагружают ГЦ больше, чем любые другие?

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

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

Не факт. Вы не учитываете усложнение алгоритма вывода типов. БОльшая часть правил вывода в том же Haskell, процентов 90, - она про ограничения и generic-и (конструкторы типов) как раз. А работает проверка и вывод типов всегда. И там сложность, минимум, квадратичная.

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

Так необходимо вывести instance.

Или указать явно. Это ортогональные вещи.

Так явное указание требует вывода и проверки ограничений, всё равно.

Сверка типов - тривиальная операция. Вывод тут никакой не нужен.

UFO just landed and posted this here

Обобщение в широком смысле слова — это ключевая аналитическая задача программиста в процессе разработки решения и моделирования предметной области.   

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

Кроме технической составляющей, я бы еще отметил, что адепты Go все эти 12 лет себя и окружающих фанатично убеждали что дженерики не нужны "by design". Однако, реальная практика всё же вынудила признать некомпетентность изначальных идей.    

Этот пример с дженериками достаточно очевидный и показательный чтобы отметить в целом всю несостоятельность и глупость дизайна Go. Поэтому используется такая фраза как "этим всё сказано".  

Ваш капитан очевидность. 

Этот пример с дженериками достаточно очевидный и показательный чтобы отметить в целом всю несостоятельность и глупость дизайна Go. Поэтому используется такая фраза как «этим всё сказано».

Ваш капитан очевидность.

Ну спасибо что хоть кто-то уделил минутку внимания чтобы объяснить что там сказано)

Про то что изначально в Go не было планов на дженерики я тоже наслышан. Просто мне почему-то показалось что корневой комментарий пытался оспорить постулаты статьи этим «всё сказано», а так он еще больше поддерживает.

А, еще видимо я слово «только» не в том значении прочитал.

Я прочитал предложение как "… статья конечно хороша, но вот только в Go уже есть дженерики с марта"
а по факту коммент был похоже
«плюсую статье, все по делу. одно лишь факт (»только") что в марте ЭТОГО года добавили..." далее по тексту.
Возможно из-за этого и был тупняк.

Всем извините, можете минусить мой тупизм дальше)

Дело не просто в том, что не было дженериков, а в том, что было: статическая строгая типизация. Сразу понятно к чему это приводило - когда реализации одного и того же метода интерфейса для разных типов приходилось писать вручную, есть целые библиотеки с кучей функций типа AddIntInt, AddInt32Int32, AddUint32Uint32 и т.д. И кодогенерация, как в "старых добрых" 60-х. Хотя уже тогда были языки с динамической типизацией вроде разных LISP, а Smalltalk появился в 1972. А Go притворяется, что сейчас 70-е. Это такой Паскаль с CSP. Со всеми вытекающими.

Как программисту на С++ мне это слушать как страшную сказку приходится) Сочувствую Go-разработчикам. Не, строгость это хорошо. Это одобряю. Но вот этот вот AddUint32Uint32 ужасно же.

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

* За тупизм извиняем.

Вот Вы говорите "наиболее популярный и эффективный". А на какой статистике Вы основываете это утверждение?

Надеюсь, вы этот вопрос написали истины для, а не потроллить. 

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

Возьмем индекс TIOBE и посчитаем популярность языков: 

Python + Java + C# + Visual Basic + Swift + PHP = 38%
C + JavaScript + ASM + SQL + Go + C++ = 29%

Чисто формально по этим цифрам дженирики наиболее популярный способ даже против суммы всех "не дженериков", а если сравнивать по отдельности, вывод будет еще основательнее.

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

Изначально в go были ограниченные дженерики -- слайсы, мапы и каналы. Но свои собственные обобщённые типы программисты создавать не могли.

Ну как добавили... как и почти все остальное в го они half-baked:

type Integer interface {

~int | ~int8 | ~int16 | ~int32 | ~int64

}

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

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

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

Я давно слежу за разработкой go и это совсем не то, впечатление, которое я получил. Как минимум, каждый год проводится survey для понимания приоритетов сообщества, я участвую в каждом. Отсутствие дженериков было обозначено как проблема номер один. Любой желающий может предложить proposal. Проблема в том, что большинство proposals ещё более half-baked, чем то, что предлагает ядро разработчиков из Гугла. В стиле "я видел фичу Х в другом языке, хочу так же". Детали не проработаны, backward compatibility не проработано, и т.д.

А что, кто-то насильно заставляет писать на Go? Не понимаю смысла этой статьи. Не нравится производительность - пиши на Си (больше заморок с памятью) или Расте (чудовищный порог входа). Не хватает выразительности - пиши на более выразительном языке (но будь готов отстаивать на кодревью правильность слоёв абстракции).

Нет такого закона, что все должны писать на Go и страдать, и нет такого закона, что все должны слезать с Go, потому что Раст круче.

А зачем писать комментарии, если получается написать только "Не нравится - не ешь"? :)

Критику можно обсуждать, опровергать, соглашаться, вот это вот всё. Это в конце концов позволяет сделать язык лучше. Но нет же. :)

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

(с) Ф. Кривин

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

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

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

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

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

Понимаю, о чем вы говорите. Несовершенство информационных технологий часто увеличивает видимость ложных ценностей и оставляет в тени реальные достижения. 

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

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

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

Да бросьте. Медийное давление, создаваемое Rust-сообществом просто беспрецедентно. С Go даже близко такого нет. Даже с Haskell в своё время такого не было. Куда ни глянь - везде только Rust и обсуждают. Ну, или другие языки в контексте того, насколько они хуже Rust. В каналах языковых телеграмма тоже сплошной Rust. Фанаты крайне активны.

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

Ну... Социальные пузыри у всех разные. К сожалению. Я живу в каналах дизайна ЯП и компиляторов. А что, в Вашем пузыре реально пиарят Go изо всех сил?

В моём пузыре вообще редко какие-то языки пиарят. Но го вспоминают чаще раста, хотя всё ещё в моих глазах несущественно редко.

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

Не, его часто вспоминают словами о том, какое же это Го..., а вот Rust - золото. Совершенно, кстати, не понятно, чего Rust-овцы недолюбливают так сильно именно Go. Типа, одна из граней противостояния Google и Mozilla, начавшегося с браузеров?

Давайте вы не будете мне рассказывать, какие я читаю отзывы о Го, ладно? :)

Нет, я не вижу никаких сколько-то регулярных выкриков "го - какашка, вперёд в раст".

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

Так я же про упоминание Go в тех каналах, которые я читаю.

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

… или Расте (чудовищный порог входа)

А вот не факт. Не, с тем, что у Go порог входа ниже, я спорить не буду. Но я вот недавно читал статью, где авторы, на минуточку, весь проект в какой-то момент переписали с C++ на Rust — и там есть, в частности, такое:


Rust can be challenging for beginners. But our interns proved otherwise. They picked up Rust within one or two weeks — even with no prior Rust/C++ expertise <...>

Это, конечно, anecdotical evidence, но всё же один из доводов в поддержку моей точки зрения, что слухи о сложности Rust несколько преувеличены.

Да люди просто насмотрятся как на Rust выглядят interop c С-либами, и потом боятся, что там весь код так выглядит. По факту Rust уж точно проще C++, который многие из нас ещё в универе изучали и ничего.

Сейчас есть определенный хайп вокруг Python и Go. И многие новички по факту начинают изучать эти языки в результате маркетингового обмана. Так что говорить о них правду вполне может быть полезно для IT-сообщества в целом.

Потому что, чтобы понять насколько плох тот или иной ЯП, надо для начала хотя бы 5 разных языков изучить, а лучше 10)

Незрелый и однобокий аргумент, на мой взгляд. Особенно в контексте обсуждения технической статьи. Что значит "не нравится производительность - пиши на Си"? С таким же успехом можно было и не писать этот комментарий, если не понимаете/не приемлете отношения автора статьи к языку Go.

Все вышесказанное относится и ко мне, если что :)

Я 7 месяцев работю тестером в достаточно большой американской комании где большая часть Back End сделанна на Go + gRPC. Я не слышу воплей девлоперов (у меня в команде их 5) что они не могут делать свою работу потмоу, что выбор языка кривой, и надо было выбрать чтото другое. Их когда нанимали, им говорили начем все написано, не хотели бы выбрали другую работу. Что за проблема? Ну не нравится тебе язык этот... не пиши на нем, не нравится что на работе на нем пишут - поменяй работу. Столько времени человек убил чтобы написать это все... такой дешевый заход на попытку привлечь к себе тонну внимания и развести срач... детский сад.

Автор совсем, критически не понимает, зачем нужен голанг.

4 года назад я пришел в большую контору (Убер, если конкретно) писать на голанге, при том что до этого я в основном занимался питоном, а все мои знания голанга ограничивались пройденным tour.golang.org (спойлер: этого достаточно). Так вот, через неделю я отрелизил первую версию библиотеки, которой с минимальными изменениями продолжает пользоваться весь убер.

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

Гугл просто решал свои задачи, ну и заодно людям дал попользоваться.

А так-то конечно да, гошный стдлиб - срамота, все потуги с управлением зависимостями до появления модулей (помните были такие glide и dep?) - это вообще откровенная диверсия - много, много всего очень плохо. Но просто и не стояло задачи написать идеальный язык :)

 Кстати, наброшу - с обработкой ошибок начиная с 1.13 все более-менее нормально :)

UFO just landed and posted this here

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

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

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

Или взять другой язык, в котором этих подводных камней нету. Да, выучить Go проще. Но изучение языка — это однократное вложение (так что предельная ценность простоты изучения языка нулевая), а вот с Go-специфичными проблемами придётся сталкиваться постоянно.

Если это однократное вложение затягивается на годы, как с Haskell, например, в силу особенностей экосистемы, то стоит ли оно того? Rust или C++ тоже простыми языками не назовёшь. Кроме того, важна метрика: время до запуска бажного MVP. Потому что баги бывают не только в коде, типах и указателях, но и в самой идее, в организации интерфейса, etc.

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

Вот так всё просто, на самом деле. Только почему-то народ предпочитает витать в абстрактных рассуждениях о тех или иных схоластических тонкостях.

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

Зачем гоферу сутки изобретать велосипед? Чай не во времена телетайпов живём. Взял готовую реализацию, подправил в ней что-то под себя, и вперёд. Ну, не 5 минут займёт, а 15. Зато потом можно будет алгоритм под свои задачи подстраивать, параметризовать каким хитрым образом. У generic-библиотек существенный недостаток: железобетонный интерфейс, который не так часто достаточен, как хотелось бы. Приходится изловчаться разными методами. Просто сложность в другое место переезжает, вот и всё.

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

Отладка, тестирование, документирование, ревью, поддержка - всё это тоже включено в 15 минут?

После С++ любой язык будет как глоток свежего воздуха. Вовсе не обязательно из одной крайности впадать в другую.

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

Один только звездец с сортировками чего стоит:

Hidden text
// A Change is a record of source code changes, recording user, language, and delta size.
type Change struct {
	user     string
	language string
	lines    int
}

type lessFunc func(p1, p2 *Change) bool

// multiSorter implements the Sort interface, sorting the changes within.
type multiSorter struct {
	changes []Change
	less    []lessFunc
}

// Sort sorts the argument slice according to the less functions passed to OrderedBy.
func (ms *multiSorter) Sort(changes []Change) {
	ms.changes = changes
	sort.Sort(ms)
}

// OrderedBy returns a Sorter that sorts using the less functions, in order.
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter {
	return &multiSorter{
		less: less,
	}
}

// Len is part of sort.Interface.
func (ms *multiSorter) Len() int {
	return len(ms.changes)
}

// Swap is part of sort.Interface.
func (ms *multiSorter) Swap(i, j int) {
	ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
}

// Less is part of sort.Interface. It is implemented by looping along the
// less functions until it finds a comparison that discriminates between
// the two items (one is less than the other). Note that it can call the
// less functions twice per call. We could change the functions to return
// -1, 0, 1 and reduce the number of calls for greater efficiency: an
// exercise for the reader.
func (ms *multiSorter) Less(i, j int) bool {
	p, q := &ms.changes[i], &ms.changes[j]
	// Try all but the last comparison.
	var k int
	for k = 0; k < len(ms.less)-1; k++ {
		less := ms.less[k]
		switch {
		case less(p, q):
			// p < q, so we have a decision.
			return true
		case less(q, p):
			// p > q, so we have a decision.
			return false
		}
		// p == q; try the next comparison.
	}
	// All comparisons to here said "equal", so just return whatever
	// the final comparison reports.
	return ms.less[k](p, q)
}

var changes = []Change{
	{"gri", "Go", 100},
	{"ken", "C", 150},
	{"glenda", "Go", 200},
	{"rsc", "Go", 200},
	{"r", "Go", 100},
	{"ken", "Go", 200},
	{"dmr", "C", 100},
	{"r", "C", 150},
	{"gri", "Smalltalk", 80},
}

// ExampleMultiKeys demonstrates a technique for sorting a struct type using different
// sets of multiple fields in the comparison. We chain together "Less" functions, each of
// which compares a single field.
func main() {
	// Closures that order the Change structure.
	user := func(c1, c2 *Change) bool {
		return c1.user < c2.user
	}
	increasingLines := func(c1, c2 *Change) bool {
		return c1.lines < c2.lines
	}
	decreasingLines := func(c1, c2 *Change) bool {
		return c1.lines > c2.lines // Note: > orders downwards.
	}

	OrderedBy(user, increasingLines).Sort(changes)
	fmt.Println("By user,<lines:", changes)

	OrderedBy(user, decreasingLines).Sort(changes)
	fmt.Println("By user,>lines:", changes)
}

В нормальных языках это делается гораздо проще:

struct Change {
	string user;
	string language;
	int lines;
}

Change[] changes = [
	{"gri", "Go", 100},
	{"ken", "C", 150},
	{"glenda", "Go", 200},
	{"rsc", "Go", 200},
	{"r", "Go", 100},
	{"ken", "Go", 200},
	{"dmr", "C", 100},
	{"r", "C", 150},
	{"gri", "Smalltalk", 80},
];

void main()
{
    
	changes.multiSort!( q{ a.user < b.user }, q{ a.lines < b.lines } );
	writeln( "By user,<lines:", changes );

	changes.multiSort!( q{ a.user < b.user }, q{ a.lines > b.lines } );
	writeln( "By user,>lines:", changes );

}

Я не шибко великий специалист по Go, но мне кажется, реализация там чрезмерно усложнённая. Я бы проще написал.

Это реализация из документации. А как бы вы написали?

А какие ограничения решение должно учитывать? Самое простое - сделать две разные реализации интрфейса "под задачи", а чтобы не писать каждый раз длинные if-then-else в реализациях Less для сравнений по ключам сделать функцию-композиции сравнений.

Может так?

package main

import (
	"fmt"
	"sort"
)

type Change struct {
	user     string
	language string
	lines    int
}

var changes = []Change{
	{"gri", "Go", 100},
	{"ken", "C", 150},
	{"glenda", "Go", 200},
	{"rsc", "Go", 200},
	{"r", "Go", 100},
	{"ken", "Go", 200},
	{"dmr", "C", 100},
	{"r", "C", 150},
	{"gri", "Smalltalk", 80},
}

func main() {
	sort.Slice(changes, func(i, j int) bool {
		return (changes[i].user == changes[j].user && changes[i].lines < changes[j].lines) || changes[i].user < changes[j].user
	})

	fmt.Println(changes)
}

В нормальных языках это делается гораздо проще


Получается go тоже нормальный?

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

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

Сортировка - это один из тысяч алгоритмов. Для Го теперь надо писать свой аналог STL. Но на примере C++ мы видим к чему всё это приводит, если язык изначально не планировался для мета программирования.

Это в каких языках нету подводных камней?

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

Т.е. ровно так же можно про любой язык говорить да и в целом про библиотеку/инструмент/подход/идею/etc. Хоть про Rust из разряда у вас не Servo, не блокчейн/etс и вообще не экспериментируйте, вон есть C. Зачем вам TypeScript, вы не Microsoft. Не используйте React, вы не Facebook. У вас JavaScript, ой ну его нафиг прототипное наследование... К чему придраться и на чём сделать упор подобной критики всегда найдётся.

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

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

Go решил задачи Google (на самом деле далеко не только их), которые были изначально поставлены, язык развивается как и всё, появляются новые ниши применения, к которым язык адаптируется (может быть медленно), но всё же и это нормально.

Касаемо различных технологий из Google, которыми многие пользуются и от которых достаточно много пытаются отговаривать (а это именно так) тоже отдельно хочется сказать. Неужели ни кто, посмотрев на Starlark/Bazel/Protocol Buffers/FlatBuffers/Android/Fuchsia/Kubernetes/gRPC/etc до сих пор не понял, что подход Google это максимальная автоматизация и куча codegen...

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

Но сам факт генерации кода пусть и не полный тот же GitHub Copilot (нравится или нет) или IntelliSense/IntelliCode могут достаточно сильно ускорить процесс написания кода, а следовательно и решения задач автоматизации, что является двигателем прогресса по крайней мере в IT. Причём кодо-генерация в целом может удешевлять будущие разработки: напиши один раз универсальный генератор для того же распространённого CRUD и экономь время и деньги на создание однотипных конструкций на языке ANY_LANG_PLACEHOLDER (естественно до первой встречи со специфичным использованием/применением).

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

А так получилась статья из разряда Little-endian vs Big-Endian, Binary vs Ternary (уже Quad, привет квантовые компьютеры), A vs B, etc. Как говорится вам шашечки или ехать, в итоге ни то, ни другое, а только философское рассуждение на тему что лучше и лучше ли оно вообще. Если философствовать то есть один ответ: мы все работая с любым набором инструментов/языков/техник/подходов делаем всё не правильно по тому, что мы даже не в состоянии определить, что правильно. Мы в науках то даже не уверены на сколько применяемые сейчас подходы в той же физике верны и применимы... За пройденную историю уже не раз видели как то, что мы считали идеалом оказывалось совсем не идеалом, да и в целом точка зрения оказывалась только под одним углом, а под другим оказывается всё работает совсем по другому.

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

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

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

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

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

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

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

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

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

Конкретно в этой статье посыл именно из ряда, "ради добра прям советую даже не используй это", хоть конечно критика затрагивала не только сам Go, другим языкам тоже досталось, однако главный объект критики в статье именно Go и что главное по всему тексту он прям вообще ни для чего не годится, только вот Google и вон те ещё ребята.

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

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

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

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

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

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

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

Если мы будем так разрушать каждую апелляцию к авторитету на право и на лево, тогда каждый должен полностью независимо с нуля вести сначала изучение физических объектов и процессов, потом самостоятельно на выше изученном создавать свои вычислительные машины, концепции (почему вообще байт код и почему двоичный?), языки и т.д. Это будет уже не прогресс, а топтание на одном месте, даже больше похоже на челлендж из разряда найди все возможные способы достижения цели. Ну серьёзно.

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

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

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

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

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

Порог входа в Питоне не сильно выше чем в Го. Да и Джавы/Колтина, в принципе, тоже. Затем, способов писать на самом деле плохой код, pitfalls типа захвата переменных по значению в цикле, и других способов наделать трудно отлавливаемых багов тоже не принципиально меньше, чем в Питонах-Джавах-Котлинах. Поэтому ваше утверждение спорно. При этом я хорошо понимаю, о чем вы пишете, я сам пару лет назад пришел в команду писать на Го, даже не дочитав tour, и со всеми другими членами команды было то же самое.

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

Можно, конечно, чисто механически натаскать человеков - вот тут перед функцией "@app.route('/list')" пиши и оно будет тебе гет запрос обрабатывать, но это для них чисто магия будет. А голанге за неделю можно прям боль-мень разобраться и понять как оно и под капотом работает.

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

Да даже ванильный HTTP-стек в го написан так что хрен разберёшься как он работает.

Но это все лирика, 95% средненьких программистов туда не полезут никогда (они в принципе не лазят никуда. Многие даже не знают, как переходить на дефинишен чего-либо кроме кода проекта, и не пользуются ИДЕшками, которые это позволяют).

Имеет значение только способность читать и писать код проекта, как он есть, плюс понимать логику фреймворков. Так вот, в Джаве оно точно не сложнее, чем в Го. Ну ок, в Питоне и Котлине с их перегрузкой операторов уже может быть посложнее. Хотя зависит от проекта. Если на проекте не используются фреймворки, которые активно используют перегрузку операторов, то и ок. Научиться читать и писать Питон и Котлин тогда не принципиально медленнее (если вообще медленнее), чем Го.

И заметьте, это не труизм, потому что это явно не так для C++, Rust, Scala, C#. Впрочем и на этих языках можно найти обозримые сабсеты, но на практике мало кто выдерживает такие стайлгайды. Хотя если кто-то строго использует C++ Core Guidelines и использует современные анализаторы кода, внезапно C++ тоже превращается в приемлемый продакшен-язык.

Вот, комментарий прямо в точку. Я только добавлю немного взгляда изнутри. Дело не столько в качестве программистов в Гугл, а в том, во что превратился там С++ и код ревью на нём.

Любой код на С++ это портянки объявлений переменных. Даже простую консольную утилиту для себя невозможно написать на чистом std. Каждый второй ревьюер будет объяснять, что надо делать по другому. В итоге реально недели ревью простого кода.

С Go эта проблема решилась. Ревью проходится за день или два. Для большинства вещей уже есть описанные правила, как делать. Язык стал инструментом решения задач а не соревнование в крутизне.

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

>при том что до этого я в основном занимался питоном, а все мои знания голанга ограничивались пройденным tour.golang.org (спойлер: этого достаточно). Так вот, через неделю я отрелизил первую версию библиотеки, которой с минимальными изменениями продолжает пользоваться весь убер.

А написание на питоне заняло бы больше времени?

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

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

Думаете, python-программисты только и заняты, что выбрасывают старый код и пишут его заново?

P.S. Проверил сайт с вакансиями UBER, что у go, что у python куча упоминаний, но в основном в контексте "Expertise in one or more object oriented programming language (e.g. Java, Go, Python, C++)". Как-то про технологии не пишут.

P.P.S. Google и Meta, вроде, не против найма новых python разработчиков, даже прости господи, Yandex таким занимается, может и нанимают для постоянного переписывания сервисов, но, кажется, если бы можно было/имело смысл переписать всё на go, они бы уже справились.

Для языковых холивоинов должен быть отдельный ад.

Ну в самом деле, если знаете, как сделать правильный язык, - делайте, да пишите на нём. Критерием того, что язык правильный, является его высокая продуктивность. Если вы сделаете правильный язык, то с небольшой компанией единомышленников сможете на нём написать что-нибудь интересное, и народ потянется. Керниган и Ричи смогли даже на отстойном по мнению многих Си, и вы сможете. Экосистема языка запустится и начнёт жить. Вот и всё. Остальное - религиозные войны. Что теория типов, что особенности синтаксиса, что пресловутый nil и т.д. Пока религия не подтверждена практикой - это пустая болтовня, какой бы красивой и логичной она ни была бы.

О nil. Как разница, от чего программа ведёт себя некорректно: от того, что по nil к памяти обратились, или от того, что не те два числа сложили, или от того, что в select забыли сокет передать? Это просто ошибки, которые бывают. Почему особое вниманием именно nil? Программы по другим причинам не вываливаются с исключениями? Взять тот же Rust, в котором нет проблем с nil. В программах на Rust повсеместно понатыканы unwrap: что-то пошло по непредусмотренному пути, программа вылетает. И? Давайте теперь изобретать язык, в котором unwrap невозможен? А что делать тогда с ситуациями, когда у программы нет информации для обработки возникшей ситуации? Просто выход с exit(code != 0)? Ну, ok, но чем это будет отличаться по сути от вываливания с исключением, если просто логика программы неверная?

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

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

Остальное - религиозные войны. Что теория типов, что собенности синтаксиса, что пресловутый nil и т.д.

Необоснованная критика. Зачем тогда в Go используются фигурные скобки? Это же все от лукавого. Мой тейк в том, что системы типов и удобный синтаксис упрощают, ускоряют и делают разработку более надежной, что неоднократно подтверждается с выходом новых языков. Например Kotlin, который как Java, только лучше.

О nil. Как разница, от чего программа ведёт себя некорректно...

Разница в ровно в том, что как nil необходимо проверять в программе (а можно и не проверять, забыть - никто тебе и слова не скажет). Если говорить о nil как о не валидной ссылке не объект, то тут усе замечательно сказали более свежие языки: нам не нужен ни null, ни null pointer exception. В одних языках это решают через type? - менее прогрессивный подход, говорящий о том, что там может быть нуль и стоит его проверить перед использованием; и более прогрессивным - примитивами из функциональных языков.

В ненавистном (любителями ассемблера от Google) Rust нельзя получить значение не обработав все возможные ситуации. Тот же unwrap - решение проблемы. Программист говорит компилятору: верни мне валидное значение или упади.

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

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

Претензия к nil, null заключается прежде всего в их неинформативности. У исключений есть текст, у option, result есть метод expect, который принимает текст и позволяет более подробно сообщить об ошибке, а с другой стороны есть магические числа и нуль - ну упало, что ты от меня хочешь :(

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

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

Необоснованная критика. Зачем тогда в Go используются фигурные скобки? Это же все от лукавого. Мой тейк в том, что системы типов и удобный синтаксис упрощают, ускоряют и делают разработку более надежной, что неоднократно подтверждается с выходом новых языков. Например Kotlin, который как Java, только лучше.

В чём отличие Вашего заявления от следующего? "Земля плоская, потому что регулярно выпускаются книги и проводятся конференции, утверждающие, что она плоская."

Единственное мне известное действительно научное исследование влияние ЯП на качество кода не выявило никакого существенного влияния ни типов, ни синтаксиса, ни наличия nil на качество. Единственное, что, возможно, слегка влияет положительно - это иммутабельность и поддержка замыканий.

https://arxiv.org/abs/1901.10220

Программисты вынуждены работать с тем, что есть, а не с тем, что объективно повышает их продуктивность. Разработчики же языков вынуждены следовать модным трендам в языкостроении, чтобы не выглядеть отщепенцами. Но эти тренды - прикладная теология, в основном. За ними нет ничего экспериментально проверяемого, за ними только рассуждения, авторитеты и личные переживания да убеждения.

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

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

UFO just landed and posted this here

И как я для float-ов это докажу за приемлемое время? Тут вон ребята из Gaulois для градиентного спуска в самой примитивной его форме доказательство писали 2 года вдесятером. Да и то, все реальные вычисления у них были на C++ и просто покрыты аксиомами (при чём, для Real, а не для Float), а не доказательствами корректности. И на плохих данных, там легко возникнут бесконечности.

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

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

Про TypeScript - это частный случай. Сам JS задизайнен странным образом, не самым удачным. Но даже в таком случае TS помогает выловить лишь 15% ошибок - это не сокращение времени отладки прямо в разы. А процесс разработки затягивается далеко не на 15%. Я сравнивал для себя время решения одинаковых задач на Scheme и Haskell.

К слову, о последнем: а что, сейчас у нас много Haskell-программистов, которые быстрее решают задачи за меньшую зарплату? Я вот, например, зная, насколько процесс программирования на Haskell выматывающий, тоже бы брал за это +50% к своим обычным запросам.

UFO just landed and posted this here

Так если это важно, тогда какие вообще вопросы? Кто-то получает удовольствие от Си, кто-то - от Раста, кто-то - от Лиспа, кто-то - от Го. Вопрос закрыт простым ответом: что вам нравится, то и используйте. Нет?

UFO just landed and posted this here

Что это говорит?

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

Это ошибки, которые были обнаружены в последующих коммитах

В смысле? Исследователи брали код в версии до правки бага, переписывали его на TS и Flow, и смотрели, вылезет ли ошибка компиляции. То есть, баг был обнаружен и исправлен.

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

Мы обсуждаем конкретное исследование. Там был использован такой метод анализа эффективности типизации.

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

UFO just landed and posted this here

тогда я впервые оказался в Портленде, штат Орегон, столице кофе, гранжа, ненастья

вообще-то это про сиэтл

Go для нашей команды оказался реальной болью, когда мы решили писать на нём кэширующий прокси-сервер. Рейс-кондишны приходится отлавливать регулярно, ведь http.Request, который передаётся по цепочке обработчиков (в том числе сторонних) - это мутабельная незащищённая структура. Причём такие штуки отлавливают и в стандартной библиотеке: https://github.com/golang/go/issues/30597

А ещё мы отловили баг в библиотеке http/2, которому уже идёт второй год и чинить его, видимо, слишком дорого и некому. При определённых условиях сервер просто-напросто зависает: https://github.com/golang/go/issues/42534

А теперь взять и переписать всё - дорого. Возможно, будем в будущем слезать потихоньку в сторону Rust или ещё чего.

Человек с ником Rustacean рассказывает что переходит с Go на Rust - хм, не вижу ничего подозрительного :3

Обе иши не ваши, переходите на пайтон или перл, чтобы не было боли, там все хорошо.

Рейс-кондишны приходится отлавливать регулярно, ведь http.Request, который передаётся по цепочке обработчиков (в том числе сторонних) — это мутабельная незащищённая структура

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

Нет здесь никаких странностей для тех, кто работает с сетевым ПО. Мы используем под капотом сервер Caddy. Вполне обычная история, когда пишется промежуточный обработчик http-реквеста в цепочке (это и в другом подобном ПО будет решаться похожим образом)

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {

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

Я так и не понял, в чём проблема. Обычно фильтры/middleware выполняются на той же горутине, и ставить мьютексы нет нужды. В Caddy как-то по-другому? Не помню, что бы встречал рейс-кондиншны на http.Request, т.к. middleware работают под той же горутиной, а если нужно что-то обработать в новой горутине, то архитектурно не совсем верно туда кидать весь http.Request вместо конкретных данных, которые нужны. Можете привести пример, где приходится ставить мьютексы?

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

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

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

В качестве примера можете поисследовать код Caddy. Хотя опять же, нет смысла это делать, отрицая наличие проблемы.

главное, что требуется много лишних телодвижений, из-за того, что http.Request — мутабельная структура, которую требуют некоторые стандартные интерфейсы, у которой нет защищённых геттеров и сеттеров

Вы говорили именно про рейс-кондишны в http.Request, мне стало интересно именно про это. Ответа я так и не получил.


Почему бы изначально не сделать http.Request интерфейсом?

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


В качестве примера можете поисследовать код Caddy

Ну тут вопрос скорее к Caddy, если это действительно проблема, можно было бы ввести свой интерфейс. Могу предположить, что проблема в интеропе с существующим кодом, где используется http.Request? В теории можно накостылять функцию-конвертер, которая транслирует между стандартными типами и своими. Нужно смотреть в конкретные примеры.


Хотя опять же, нет смысла это делать, отрицая наличие проблемы.

Я не отрицаю проблемы, просто на практике не встречался с ней, поэтому и интересны примеры. Кто знает, может быть, у нас есть потенциальные проблемы.

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

Все или ничего (так не будем же делать ничего)

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

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

Тулчейн Go не работает с ассемблером – языком, известным везде. Он не использует тех линковщиков, с которыми все работают. Он не позволяет вам работать с общеизвестными отладчиками

Не очень понятно, с какими такими универсальными линковщиками все работают? Может быть автор имел в виду стек gcc? Довольно редкий кейс, чтобы тулзы для технологии X работали для технологии Y. Как и у других технологий, у го есть свои инструменты. Кроме того, программы на го точно так же можно отлаживать и инспектировать используя стандартные инструменты на уровне OS.

При вызове Go откуда угодно требуется запихать всю среду исполнения Go.

<прочие недовольства интеграции с c>

Изложено так, как будто это проблема. На практике нет. (го рантайм весит 1-2 мегабайт). Что касается отслеживания дескрипторов и прочего - примерно то же самое будет и с интеграцией другого языка с GC и си.

А ещё вы можете легко и непринужденно не заморачиваться по поводу многих вещей, когда пишете код на Rust. <пример с UTF-8 и сторонним крейтом camino>

В го, как и в других экосистемах, тоже можно пользоваться готовыми библиотеками (в т.ч. и для обработки UTF-8). Не понятно, к чему это написано.

Пост очень эмоционально написан, явно негативно окрашен. Некоторые аргументы притянуты за уши. Выглядит так, как будто вместо того, чтобы изучить подход, техники и стиль, человек пытался ментальную модель другого языка натянуть на го. Как-то видел фразу в комьюнити: "не программируйте на java в го".

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

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

Вопрос всегда упирается в область применения. Если на Go не писать монстров типа Кубернетеса, а ограничиться, например, вебом и микросервисной архитектурой, то маленькая программулька, делающая одну вещь, и делающая её относительно хорошо - это идеальный вариант применения Go. Ведь такую программульку очень легко объять взглядом одного человека и написать всё качественно.

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

А если вам надо в ядро Линукса, так берите Rust, не задумываясь! Там он очень даже к месту.

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

А маленькую программульку почему бы не написать на более выразительном языке? Кода получится в 2-3 раза меньше и объять взглядом его будет ещё проще.

Ещё раз: выше в коментах вспомнили, что именно скоростью компиляции авторы Go оправдывают свои спорные решения. Никто вроде не утверждал, что они в этом преуспели.

А по поводу статьи, вы специально искали график, где D выглядит лучше всего?)

Это наиболее репрезентативный график.

Ничего не могу сказать про D и Go, но время компиляции C++ быстрее растет от активного применения темплейтов, а не от количества функций.

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

UFO just landed and posted this here

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

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

Да и насчёт выразительности языка я не соглашусь. 90% выразительности - это простота и быстрота читаемости. Остальное - чепуха. Вы пробовали читать код на Go? Его поймет ребенок. И не требуется тратить время на тома со стайл-гайдами. Если итерацию можно сделать пятнадцатью разными хитрыми образами, это не добавляет выразительности языку. Чем "тупее" и прямолинейнее программа, тем меньше шансов в ней запутаться, тем проще её поддерживать в команде.

Вы пробовали читать код на Go? Его поймет ребенок. 

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

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

Чем "тупее" и прямолинейнее программа, тем меньше шансов в ней запутаться

Ну вот "тупее и прямолинейнее" - это про какой-то другой язык, увы.

UFO just landed and posted this here

Вы пробовали читать код на Go?

К сожалению, да. Чтобы код был понятнее, он должен быть лаконичным и отделять happy path от всего остального, а если ещё DSL можно сделать, то в итоге может и правда даже ребёнок поймёт. Вот только в Go нельзя by design сделать ни то, ни другое, ни третье.

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

Описали. Но все эти пункты применимы и к другим языкам. У Go тут нет какой-то уверенной позиции по этим пунктам. Разве что по простоте деплоя он в лидерах.

А взять тот же инструментарий, гоферы в итоге определились с управлением зависимостями? Я на нём писал то всего год, и то 5 разных вариантов видел, и это в то время, когда почти каждый ЯП уже шёл со стандартизированным менеджером зависимостей. Так что по инструментарию Go где-то в рядах догоняющих с большой тягой к изобретению велосипедов.

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

У вас причина и следствие перепутались.

Нет. Если кто-то хочет поменять отношение к языку, то нужно идти именно этим путем. Мало пользы объяснять, что С++ плохой язык с т.з. дизайна - это и так понятно, но бизнес смотрит на другие особенности.

Бизнес ничего не понимает в программировании, он смотрит на следствие выбора программистами в лучшем случае и маркетологами в худшем.

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


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


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

Тем не менее, чем приятнее программисту язык — тем за меньшие деньги его можно нанять.

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

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

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

Так все разработчики

А где у меня в комментарии вы увидели отрицание этого?

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

но согласитесь, "это показатель уровня кривизны рук и лени" не то же самое что "это кривые руки и лень"

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

UFO just landed and posted this here

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

Articles