Блог компании OTUS. Онлайн-образование
Go
Комментарии 25
+3
Несмотря на некоторый хейт Golang на Хабре, наш внештатный автор решил рискнуть продолжить серию статей

Может все-таки хейт не Golang, а вашего автора/компании/качества статей? Лично я хейта на Golang не заметил.
0
Возможно наш читатель действительно ждет чего-то более хардкорного от нашего блога. Мы не исключаем этого и в принципе готовим на будущее более «инженерный» материал. ЧТо касается хейта, вот, например, очень яркий пример habr.com/ru/company/netologyru/blog/471782
+5
Функции первого класса (high order function)

Какая-то каша из англоязычных терминов first class citizen и high(er) order functions. Это не одно и то же.

ООП в языке реализуется, пускай и достаточно непривычным способом, через систему структов и интерфейсов

Было бы интересно, если бы автор (преподаватель языка?) пояснил вот это предложение некоторыми примерами или просто текстом. Что имелось в виду? (Без подвоха — действительно интересно)
0
Какая-то каша из англоязычных терминов first class citizen и high(er) order functions. Это не одно и то же.

Ну, это, конечно же, не одно и то же — но вот одно без другого в нормальных языках существовать не может. Если функция — first class citizen, то её автоматически можно принять как параметр или вернуть как результат, т.е. сделать high order function. В обратную сторону это "автоматически" не работает (можно представить язык с HOF, но с особыми функциями), но напрашивается.

0
лучше за меня ответит вот эта статья, только она конечно давненько вышло, но ничего особенно с того момента не поменялось. habr.com/ru/post/225907
+4
вроде бы взрослый компилируемый язык, однако понятие классов и наследования отсутствует в принципе

Это нестрашно, и дело совсем не в этом. В конце концов, в том же хаскеле тоже нет (ООП-подобных) классов и наследования. А чтобы понять, в чём дело, давайте посмотрим на ваших же примерах.


На самом деле вовсе не обязательно самостоятельно придумывать с нуля свой map или foreach.

А можете всё-таки придумать такой map, который бы работал со списками с произвольными типами? И не через interface {}.


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

Там же везде interface{}. Какие гарантии типобезопасности даёт компилятор?


Приведем пример замыканий и карринга в Go

Ух ты, клёво, смогли каррировать функцию, принимающую два инта. А можно написать функцию curry :: ((a, b) -> c) -> a - >b -> c (пардон за негошный синтаксис, просто словами это говорить уж больно неуклюже)? Только чтобы без interface{}.

-2
Писать в функциональном стиле на Go — либо развлечение для ума, либо глупость. Всем желающим можно ознакомиться с видео Франсеска Кампоя на эту (и другие похожие) тему.
Дальше у вас стандартные вопросы-претензии к языку: «а можно ли в Go так и эдак».
Отвечаю как разработчик Go: так нельзя и эдак не выйдет. Такой язык, не всем нравится.
+2
Такой язык, не всем нравится.

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


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

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

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

А в вашем комментарии нет ответа на вопрос — есть только ещё вопросы к языку. Таких можно придумать к какому угодно языку.
В Go мало языковых возможностей — «Неудобно, приходится переизобретать велосипеды!»
В JavaScript реализованы все парадигмы и куча возможностей — «Помойка, как их вообще запомнить!?»
Ну и так далее.
Я пишу на Go — в моём случае задачи решаются на этом языке легко и эффективно. Обобщённого программирования иногда не хватает, а так — всё нормально.
+3
Претензии сообщества принимаются к сведению и обобщённое программирование обещают сделать.

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


А в вашем комментарии нет ответа на вопрос — есть только ещё вопросы к языку.

Ответы на них известны: «нельзя», разве нет? Так что это риторические вопросы, если хотите.


Таких можно придумать к какому угодно языку.

Вы абсолютно правы! И лично у меня претензии и вопросы есть ко всем языкам, которые я ковырял достаточно плотно, от плюсов до хаскеля с идрисом. Только это могут быть претензии очень разного уровня, и в других языках может быть что-то, что на эти вопросы-претензии отвечает и оправдывает использование языка даже со всеми его недостатками. А вот Go или JS — не оправдывает. Ну, лично для меня. YMMV, конечно же.

0
А вот Go или JS — не оправдывает.

У Go два оправдания: простая многопоточность из коробки на CSP и компилируемость в бинарник. Да, это можно сделать например на C++, но желающих не так много.

+2
У Go два оправдания: простая многопоточность из коробки

Ага. Простая.


компилируемость в бинарник

В единый бинарник? Если честно, ИМХО это какое-то сомнительное преимущество. Ну, то есть, да, хорошо, но чем плохо иметь более чем один бинарник? Всё равно деплоить будете либо заворачиванием в пакеты типа deb/rpm, либо в докер.

0
В единый бинарник?

Можно и в статический и в динамически линкуемый. Тут все как в C/C++.


Для микросервисов размеры важны. Статически скомпилированный бинарник занимает очень мало места. Как следствие время старта того же контейнера на непрогретой ноде очень малое. Аналогичный по функционалу контейнер на Python или Java будет занимать на порядки больше места. Да, понятно, что после первого запуска слои окажутся на ноде и все будет хорошо, но сам первый запуск может быть сложен по io. Особенно это заметно на ad-hoc запусках в разных PaaS средах, типа Heroku, Yarn и подобных.

-3
А можете всё-таки придумать такой map, который бы работал со списками с произвольными типами? И не через interface {}.
А зачем? Где это используется? Например в java?
+5
А зачем?

Зачем с произвольными типами? Или зачем не через interface {}?


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


Где это используется? Например в java?

Про джаву не скажу, я на ней не пишу и её не знаю, а на тех языках, где пишу (в основном C++ и Haskell) это используется регулярно.

0
и говорить, что у Go строгая типизация, как-то странно

Уточнение: и говорить, что у Go статическая типизация, как-то странно. Строгой (сильной) типизации никакой interface {} не мешает.

-2
> придумать [для Go] такой map, который бы работал со списками с произвольными типами

Это в теории можно реализовать, через unsafePointer. Но ни о каких гарантиях типобезопасности речи и не будет, естественно. Как и о гарантииях отсуствия сегфолтов =)
0
В C++ есть map с произвольными типами? Можно пример где это может понадобиться? Я не могу придумать ничего кроме как получить неизвестные данные, и их структурировать.
UPD. Почему то не в ту ветку попало. Вопрос к 0xd34df00d.
+2
В C++ есть map с произвольными типами?

Да, называется std::transform. Или в ranges есть. Или у меня самописный костыль в одном из моих проектов (который писался до ranges).


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

Почему? Типы данных вполне известны, просто они в каждой точке вызова map могуть быть различными. Где-то вы умножаете каждый int в массива на два при помощи map, а где-то — парсите каждую строку в массиве в жсон-объект.

0

Вот про json думал. Но там же структура известна. Зачем там interface{}? Про не известную структуру не говорим. Мы точно ожидаем определённую структуру. Тогда и интерфейс не нужен. Про int наверное что то
Узкоспециализированное? Не сталкивался. Std::transform это не конструкция языка, а подключаемая библиотека. Так?

+3
Вот про json думал. Но там же структура известна.

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


И тогда у вас одна функция map один раз инкапсулирует в себе логику пробегания по массиву (или по слайсу, или по чему вашей душе угодно), и всё.


Std::transform это не конструкция языка, а подключаемая библиотека. Так?

Именно. А в Go её написать не получится.

0
Можно подключить внешний кодогенератор. Чем макросы в плюсах и являются, в принципе.
+1

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

0
Вот про json думал. Но там же структура известна. Зачем там interface{}?

В Go вся работа с JSON идёт с помощью интерфейсов.

	rv := reflect.ValueOf(v)
	if rv.Kind() != reflect.Ptr || rv.IsNil() {
		return &InvalidUnmarshalError{reflect.TypeOf(v)}
	}


Это — кусок функции десериализации (Unmarshal) пакета json. Вызывается пакет reflect — а там всё на пустых интерфейсах.
-1
Почти каждая статья подобного рода скатывается в срачи на тему «почему в го нет дженериков»
Только полноправные пользователи могут оставлять комментарии., пожалуйста.