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

Мантра гошников: «В Go этого нет», «В Go это реализовано иначе»
Абсолютно правильная статья
Первая проблема решена (мной :) ): https://github.com/Djarvur/go-enumsafety
Каналы в Go сделаны неудобно. Начнём с того, что посылающая и принимающая сторона выражена одним и тем же типом
Есть <-chan и chan<-
Не знал. На этот счёт есть офф документация? Просто в tour of go этого точно нет
Понятно, это действительно решает описанные мной проблемы. Жаль что в гайде по языку об этом ничего не сказано. Кстати, в какой версии языка это добавили? Просто интересно почему по умолчанию предлагают везде использовать менее безопасный вариант.
-----------------------------------
Не понимаю за что мне заминусили комментарий, ну да ладно
Кстати, в какой версии языка это добавили?
В v1.0.0 было https://github.com/golang/go/blob/go1/doc/go_spec.html#L1256
Не понимаю за что мне заминусили комментарий
Наверное, не понравилось, что опираетесь, по сути, на ознакомительный тур.
В tourofrust каналы вообще не упоминаются, вроде.
Тут можно почитать https://go.dev/ref/spec#Channel_types
Первый недостаток Go -- это отсутствие перечислений (enum).
Поэтому объявляют специализированный тип и набор констант через iota и не парятся. Или используют кодогенератор и не парятся. Или используют пакет enum и его дженерики и снова не парятся.
Важная особенность состоит в том, что компилятор принуждает программиста либо обработать все возможные варианты, либо создать ветку, которая будет обрабатывать все варианты, не подпавшие под какой-либо шаблон:
А если ни то ни другое не нужно? Это, кстати, философски значимо - компилятор для программиста или программист для компилятора? Или даже так - что первично, процесс работы или её результат? Можно сказать, что Go помогает программисту автоматически создавая ветку по умолчанию которая не делает ничего.
А ситуацию когда есть набор вариантов из которых нужно выбрать ровно один на Go можно оформить массой способов - в Go функции are first class citizens.
Почему эта задача плохо решается с помощью Go. В Go для этой задачи придётся использовать обычный int
Не "придётся использовать", а "я не могу придумать ничего кроме".
Главный неприятный момент при работе с памятью в Go -- это то, что не понятно, когда переменная хранится на стеке, а когда в куче.
Согласен, то, что об этом можно не думать - большое достижение авторов языка.
Можно было бы сказать, что это просто особенность Go -- что там более высокоуровневая модель памяти. Но так как он позиционируется как язык, на котором можно писать высоконагруженные системы, то это я считаю минусом
Некоторе системы требуют писать без выделения и освобождения памяти, но это к слову. Сама же идея интересная - кем позиционируется? Где? Когда? Зачем? Я вижу что про языки программирования несут чушь на уровне торгашей базарных и пропагандистов продажных, но не понимаю кто заказывает эту музыку.
Писать высоконагруженные (то есть с фиксированным временем реакции, что-ли?) системы на Go точно можно, но что для Go, что для Rust точно найдутся такие, что их проще писать на другом языке. Elixir не даст соврать... И чё?
Много неудобств доставляет ограничение, запрещающее генерики в методах структур.
Это долгая история. Просто выясните когда в Go появились дженерики и почему не появлялись раньше. И осторожнее - Rust вообще весь состоит из неудобств, и ничего.
Таким образом, Go подталкивает нас к использованию интерфейсов
Ну вот... понимают если захотят.
Из-за того, что кортежи -- это не настоящий тип, мы не можем их использовать в генериках:
Не "не можем", а "не должны". Извращаться можно где угодно, но зачем? Кортеж - собранные вместе несколько значений. Ничего не напоминает? А их возвращение из функции - синтаксический сахар, полезность которого доказана обработкой ошибок. Как и := оператора...
Сделаю небольшую ремарку про злоупотребление интерфейсом any -- плохая практика, которая встречается не так уж редко.
Да, у Go есть история.
Это полный трэш и по сути игнорирование строгой типизации языка.
Философия языка для программиста или наоборот? Это хорошо понимали профессионалы которые делали Go, и весьма недооценённый Dart из той же конюшни, кстати. Поэтому any никогда не была трешем... разве что ловушкой для любителей.
В подходе, который в Go выбран для обработки ошибок, мне нравятся две вещи: передача ошибок через возвращаемое значение функций (по сравнению с исключениями в C++, Java) и возврат ошибки как отдельного значения (по сравнению с использованием "особых значений" как в C).
Ну не надо такое писать, дурно пахнет. Да, все так пишут, запах только усиливается. В Go перехватывается panic...
Первая проблема с таким подходом в том, что по сигнатуре функции нельзя понять, какие ошибки внутри неё могут возникнуть.
Это уже зашкаливает. Используйте другой тип и всё. Если Rust создаёт выученную беспомощность заставляющую использовать только то, что есть в стандартной библиотеке, без изменения, пусть и не всех (на меня вот не подействовало), то это проблема Rust.
И это приводит к проблемам -- так как ошибки в Go обычно имеют тип
error, то каждая новая ошибка будет присваивать значение всё в ту же переменную:
То же самое опять. "Обычно" не значит "всегда".
И у вас появляется переменная, существующая на протяжении всей функции, которую можно случайно использовать.
Давно решено. См. := оператор.
Сложно не упомянуть о синтаксическом сахаре в виде
?.
Спасибо что упомянули. Это как раз то, что было сознательно отвергеуто в Go. Упрощает и без того тривиальное ценой усложнения и так нетривиального.
Вариант, возможно, и более явный, но, мне кажется, возможность ошибки хуже неявности.
Отличное наблюдение. Действительно, в Go возможность ошибки - последний приоритет. Пытаюсь догадаться почему так - потому, что у каждой ошибки есть причина, и проще и лучше устранять причины, чем бороться со следствиями, особенно бороться запретами (вне программирования эту мысль прошу не думать). Но что думали авторы Go - не знаю.
Непонятно, что мешало за столько лет существования языка добавить банальное:
Да, в Go есть история и изначально в конструкциях языка была некоторая магия. Что лучше, append или .Push - не очевидно, это разные вещи потому, что append добавляет элемент не в массив, а в slice.
Видите баг? Мы создали массив, в котором уже есть 10 элементов.
Не вижу. Создали массив из 10 элементов. Молодцы. Не хватает фантазии сообразить когда это нужно?
Непонятно, что мешало сделать для массива пустого и массива заполненного два отдельных конструктора.
Я бы первым делом заподозрил array literal.
Начнём с того, что посылающая и принимающая сторона выражена одним и тем же типом:
Не понимаю. У канала нет принимающей и посылающей стороны, есть чтение из канала и запись в канал. И, как мне кажется и, конечно, не более того, именно каналы сделали все навороты Rust о которых любят петь как о fearless concurrency просто ненужными.
В Go присутствует такая эзотерическая конструкция, как теги на полях структур.
Да, и судя по предложениям по поводу в статье по соседству, её авторы переоценили уровень своих пользователей. Это весьма печально, особенно если задуматься о том, что рост популярности автоматом снижает тот самый уровень.
Тогда после вызова специальной команды
go generateбудет произведена генерация кода. Это очень хрупкий подход, потому что корректность написанной вами команды не проверяется никем.
Нет, не хрупкий. Эта команда применяется для запуска генератора и больше ни для чего. Результат работы генератора проверяется наравне с остальным кодом. На макросы в Rust даже не похоже.
А мы не можем, потому что родительский модуль использует дочерний, поэтому дочерний модуль не может импортировать namespace ошибок из родительского.
И не должны мочь. По определению родительский модуль использует дочерний.
В Go выбран странный подход к именованию модулей. В начале каждого файла должно быть написано название модуля, к которому относится файл. При этом, если в рамках одной папки есть файлы с разными именами модулей, мы получим ошибку компиляции.
В лучшем случае - не "странный" а "избыточный". Возможно потому, что файлы с разными именами пакетов могут присутствовать в одной папке не вызывая ошибок компиляции.
Существуют //go:build тэги, возможность явно перечислить файлы в коммандах run и build, ссылки в файловой системе, файл go.work. Вместе вот это всё позволяет раскладывать файлы по папкам крайне кучерявым образом, но я не могу придумать когда такое действительно нужно. Может быть для генераторов кода? Может быть тогда эта избыточность понадобится. А может просто избыточность введена для того, чтобы было проще обмениваться файлами по почте? Не знаю...
Про Go любят говорить, что его философия -- это простота (а также любят говорить, что каждая новая концепция, добавляемая в язык, лишает его простоты). Но в чём смысл этой простоты, если она делает инструмент негибким, неудобным для применения?
Ещё раз, мало ли что и из каких соображений врут говорят. Возьмём два slice (среза?) от одного массива и начнём их изменять - ничего от простоты Go не останется. Напишем горутины и сравним работу кода на десктопе и в Web Assembly - результат тот же. И далее везде.
Я бы мог согласиться с тем, что Go прост, если бы из контекста следовало, что он идеологически прост. Это не означает ни низкого порога входа, ни удобства для не понимающих сути языка, что Вы и описали. Как пример - Scheme и того идеологически проще... И ещё более охотно я бы согласился с тем, что Go идеологически прост и практичен.
Смысл, как мне кажется, в том, что простота упрощает эволюцию языка, что исключительно важно если хотеть чтобы Go был надолго, и облегчает изучение языка. Да, я считаю что знание языка программирования бинарно - либо есть либо нет, если не знаешь чего-то, значит не знаешь ничего, а рассуждения про уровень джуниора и сеньора, базовые и продвинутые функции - тяжёлый бред.
Негибкости и неудобства я пока в Go не почуствовал. Наоборот, с Go приятней работать чем с чем-либо ещё. Следующий за Go вариант - сладкая парочка JavaScript + Dart. Rust мне тоже нравится, наличие архитектурных ошибок странностей не особо мешает, но пользовать его можно только если время ожидания окончания компиляции хорошо оплачивается.
После некоторых колебаний решил таки отредактировать пост и добавить - Rust представляется мне хорошей заменой C++, к сожалению идущей дорогой C++.

Go после Rust: краб и суслик