LINUX.ORG.RU

Чем плох Go?

 , ,


4

14

Отчего многие его так не любят, что с ним не так? Ну кроме того, что:

  1. Нет дженериков, укуренные решения вроде sync.Map interface{} в stdlib как следствие;
  2. Базилион способов объявить переменную;
  3. Магические функции new() и make(), которые работают только с некоторыми типами;
  4. Выбивающиеся из общего стиля ЯП iota вместо enum, <- и ->;
  5. Сильно ограниченные константы, пригодные только для базовых типов данных;
  6. Кастрированные кортежи;
  7. Бесполезность поддержки unicode в коде ввиду того, что экспортированы могут быть только элементы, начинающиеся на символ из ограниченного подмножества;
  8. Unicode code point'ы можно складывать как числа;
  9. Впиндюренные в сам ЯП, а не в библиотеку «горутины»;
  10. Невозможность форка проекта с сабпакетами (он не скомпилируется с помощью go get/go install, официальная рекоммендация - использовать sed);
  11. Сообщество, которое в каждом объективном дефекте видит глубокий смысл и большой плюс;
  12. Go 2, который не пофиксит ничего из этого, кроме дженериков.

Вроде, не критично всё это, жить можно же?



Последнее исправление: cetjs2 (всего исправлений: 1)

Ответ на: комментарий от Siado

надо тыщи типов обрабатывать

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

Тогда уж добро пожаловать на динамических ЯП

А вот в жабку завезли дженерики и теперь не нужно никаких «динамических ЯП».

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от feofan

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

ЛОЛ ЧТО? Не, я понимаю, там массивы и map на стеройдах из коробки, а так то без дженериков даже пукнуть нельзя было бы. Но чуть тебе понадобиться класть объекты куда-то кроме волшебных массивов, то всё - приехали.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

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

saahriktu ★★★★★
()
Ответ на: комментарий от hateyoufeel

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

Например, больше бинарников влазит на дискеты и флэшки на 512 Мб.

saahriktu ★★★★★
()
Ответ на: комментарий от anonymous

А то, что синтаксис наркоманский — ничего?

Это ты еще rust не видел...

anonymous
()
Ответ на: комментарий от saahriktu

А теперь представьте себе, что всё это написано на Go, а потому каждый такой бинарник весит этак по 2 мегабайта.

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

find /sbin /bin /usr/bin /usr/sbin /usr/local/bin/ /usr/local/sbin/ | wc -l
3547

Если бы всё это хозяйство было написано на Go, оно бы весило около семи гигабайтов. Тогда как сейчас мы имеем

du -sch /sbin /bin /usr/bin /usr/sbin /usr/local/bin/ /usr/local/sbin/ 
16M     /sbin
14M     /bin
647M    /usr/bin
35M     /usr/sbin
209M    /usr/local/bin/
4,0K    /usr/local/sbin/
919M    total

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

find /lib /usr/lib /usr/local/lib/ -name "*.so"  | xargs du -k| awk '{sum += $1} END {print sum / 1024}'
1045.83

Итого: 7 Гб для статической сборки против 2 Гб для динамической. Много это или мало? На винте в 1 террабайт это пол процента. И если этот винт стоит 50 евро, то от динамической сборки мы выиграем 25 центов. Не уверен сколько сейчас стоят спички, но вроде должно хватить.

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

А какая вам разница как пользователю? О том у майнтейнера голова болит.

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

Лет 20 назад это наверное действительно была проблема.

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

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

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

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

feofan ★★★★★
()
Ответ на: комментарий от saahriktu

и компами-флэшками, где встроенные SSD на 32 гига?

Это частный случай и для него можно придумывать всякие извращения: динамическую линковку, кастратские сборки libc, busybox и т.д. К серверам и рабочим станциям эта возня не имеет никакого отношения.

ugoday ★★★★★
()

GoLang замена Python.

GoLang создавался как замена Python, я для этой задачи все перечисленные недостатки - и не недостатки вовсе, а рассуждения в стиле «Ложка - плохой инструмент, потому что на нее не помещается лопата песка и еще она гнется, когда долбишь гранит».

Так что прежде чем писать слово «недостатки» опиши круг задач, которые ты собрался решать. В SQL тоже присутствуют все эти недостатки, но чё-та никто не ноет, что в SQL нед дженериков.

anonymous
()
Ответ на: комментарий от no-such-file

Но слайсы и мапы таки есть. Еще есть интефейсы (не пустые).

feofan ★★★★★
()
Ответ на: комментарий от ritsufag

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

Jetty ★★★★★
()
Ответ на: комментарий от feofan

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

2. Файрфокс/Хром всё равно отожрут столько гигабайт памяти на свои нужды, что экономию на линковки с лупой не разглядишь.

ugoday ★★★★★
()
Ответ на: комментарий от anonymous

Я видал одного такого парнишу, который тож так говорил про депенденси и ноду... А потом прифигел когда выяснил что 70% исходников у него в продублированных депенденсях (привет фонгап)

Jetty ★★★★★
()

Любой тред про Gо это:

1. Нет дженериков! 2. Как это нет, есть дженерики!

/thread

Alve ★★★★★
()
Ответ на: комментарий от ugoday

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

Jetty ★★★★★
()

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

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

anonymous
()

объясните посоны

что там за интерфейсы без ООП. не понятно

даже кто-то говорил что там интерфейсы вместо дженериков

icefreeze
()
Ответ на: комментарий от icefreeze

что там за интерфейсы без ООП. не понятно

Утиная типизация. Интерфейс утка: может крякать. Тогда, если может крякать, значит утка. И можно использовать везде, где требуют утку.

feofan ★★★★★
()
Ответ на: комментарий от Jetty

Похоже у Вас была мысль, но она потерялась в процессе.

ugoday ★★★★★
()
Ответ на: комментарий от feofan

плюсовые шаблоны увеличивают время компиляции

И кому это мешает в реальной разработке? Когда ведешь разработку в IDE, каждая сборка инкрементальная - много времени не займет, когда делаешь окончательную сборку или в CI - время сборки значения почти не имеет. Какие-либо сложности могут быть только у компаний с ООООчень крупными проектами, типа Яндекса, но таких меньшинство и у них есть специальные люди, которые оптимизируют сборку проекта, чтобы время было приемлемым.

Время сборки шаблонов - это клевый повод поболтать на ЛОРе, не более.

anonymous
()
Ответ на: комментарий от anonymous

И кому это мешает в реальной разработке? Когда ведешь разработку в IDE, каждая сборка инкрементальная - много времени не займет

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

feofan ★★★★★
()
Ответ на: комментарий от eao197

А как же D? Тамошние шаблоны разве увеличивают время компиляции или время исполнения?

А еще там есть GC и миксины. Вообще супер язык - только мертвый. И пользуются им упертые фанатики и велосипедолюбители.

Выключай уже режим троля.

anonymous
()
Ответ на: комментарий от feofan

Быстрая компиляция один из базовых принципов и одно из преимуществ над крестами.

Делай рабочие сборки без оптимизаций, а окончательную сборку и финальные тесты гоняй на Release сборке. Финальная сборка делается один раз и тут время сборки особого значения не имеет.

Все. Вопрос решен.

anonymous
()
Ответ на: комментарий от nonimous

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

Время синтаксического анализа значения не имеет (оно ничтожно). Время там тратится на инстанциирование шаблонов каждый раз, когда они используются в единице трансляции (std::vector<int> vec; в разных .cpp файлах приведет к созданию экземпляра конструктора по умолчанию для каждого такого файла). А потом во время линковки из всех одинаковых экземпляров выбирается один.

anonymous
()
Ответ на: GoLang замена Python. от anonymous

чё-та никто не ноет, что в SQL нед дженериков.

Наверное, это всё от того, что SQL — не язык программирования.

hateyoufeel ★★★★★
()
Ответ на: комментарий от feofan

Даже с такими ухищрениями оно чаще всего будет собираться дольше.

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

anonymous
()
Ответ на: комментарий от anonymous

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

feofan ★★★★★
()
Ответ на: комментарий от icefreeze

не понял только что там за интерфейсы если нет ООП

Это спорно. Инкапсуляция имеется (все элементы, которые начинаются на capitalized символ - публичные, если файл в волшебной директории internal/ - внутренние, остальные - приватные). Классов нет, но struct выглядит как класс и крякает тоже как класс. Экземпляры этого «класса» создавать можно. Абстракции строятся. Наследование имеется, можно даже множественное эмулировать с помощью embedding'а, о чём недоумевают в /dev/nullExperience Reports. Для полиморфизма есть interface. В итоге ребрендированный ООП под торговой маркой Simplicity (TM).

SwiftRocks
() автор топика
Ответ на: комментарий от Jetty

А отсутствие дженериков - это малый или средний?

мизерный

Интересно. А можно пример большого?

tailgunner ★★★★★
()
Ответ на: комментарий от quantum-troll

Однако каким-то образом Swift и Sixten решают сразу обе проблемы:

У Swift своя реализация дженериков, подсмотренная у древнего советского компилятора Clu. Она да, дает быструю компиляцию.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 2)
Ответ на: комментарий от feofan

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

anonymous
()
Ответ на: комментарий от anonymous

Вот только в памяти она будет лежать вся, а не только её полезная часть

Это, конечно, вранье. В памяти будет только необходимая часть.

tailgunner ★★★★★
()
Ответ на: комментарий от RedPossum

Единственный его минус вот этом...

А вот ниже, например, плюс?

В условном Swift:

func modify(list: [Int]) {
	list[0] = -1
}

var lst = [1, 2, 3]
modify(list: lst)

print(lst)
// Output: а не лососнуть бы тебе тунца, дружок,
// параметры функции - неизменяемы и передаются по значению.

Маленькая модификация и оно работает ([Int] можно заменить любым другим типом - String, [Double], etc., поведение консистентное):

func modify(list: inout [Int]) {
	list[0] = -1

	// Можно присвоить новое значение всему массиву так:
	// list = [9, 8, 7]
}

var lst = [1, 2, 3]
modify(list: &lst)

print(lst)
// Output: -1, 2, 3
//
// Закомментированный результат: 9, 8, 7

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

package main

func modify(lst []int) {
	lst[0] = -1
}

func main() {
	lst := []int{1, 2, 3}
	modify(lst)

	println(lst)
	// Output: -1, 2, 3
}

Значение поменялось (при этом, если попробуем поменять list []int на s string - получем новое поведение, т.к. строки неизменяемы). Но весь слайс поменять при этом нельзя (никаких ошибок, конечно, не будет, всё норм):

package main

func modify(lst []int) {
	lst = []int{9, 8, 7}
}

func main() {
	lst := []int{1, 2, 3}
	modify(lst)

	println(lst)
	// Output: 1, 2, 3
}
Для этого пришлось бы делать так:
func modify(lst *[]int) {
	*lst = []int{9, 8, 7}
}

func main() {
	...
	modify(&lst)
}
В этом случае можно и отдельные элементы менять тоже:
func modify(lst *[]int) {
	(*lst)[0] = -1
}

А всё потому, что «по значению» передаётся только указатель на реальные данные и длина. В результате в ужасно простом Go можно менять свойства объекта, даже если он передаётся не как указатель. Однако, строки менять нельзя. Но вне зависимости от типа можно присвоить переменной новое значение, если это указатель (e.g. *string или *[]int), а так же поменять значение полей.

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

SwiftRocks
() автор топика
Ответ на: GoLang замена Python. от anonymous

но чё-та никто не ноет, что в SQL нед дженериков.

Упоротость гоферов не перестаёт удивлять.

RazrFalcon ★★★★★
()
Ответ на: комментарий от ugoday

1. Зависит от либы. Именно поэтому существует musl, ибо glibc линкуется целиком даже в статике.

2. Они и так почти не зависят от системных либ.

RazrFalcon ★★★★★
()
Ответ на: комментарий от Alve

К счастью, у него ещё вагон и тележка недостатков.

RazrFalcon ★★★★★
()
Ответ на: комментарий от SwiftRocks

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

feofan ★★★★★
()
Ответ на: комментарий от tailgunner

waste of space: entire lib is loaded into memory even if only a subset is used (unless the used objects and functions are in one place, but this reordering is not done by default)

Видимо, в моём приходе секты Роба Пайка выдали протухшую методчику. Есть ссылки на то, как это сейчас делается?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.