Как стать автором
Обновить

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

согласен с автором добавлю отсебятины

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

а благодаря строгости компилятора и четкости инструкций на официальном сайте
все пишут код более/менее в одном стиле, а это согласитесь многого стоит
Осмелюсь поблагодарить за статью! Действительно вчерашний пост (про «ужасный» язык) оставил в голове какое-то впечатление сумбура. Сейчас оно отступило :)
У меня оно еще не скоро пройдет ))
Что касается golang, мне, как плавно переходящего с PHP, новый ЯП все больше начинает нравиться. Есть конечно же определенные нюансы, но это все равно большущий шаг вперед.

P.S.: по части WEB, разумеется!
В комментариях к посту автора я попросил хотя бы одного человека привести три примера из своего реального кода, где ему нужно было бы вставлять элемент в середину массива — не написал никто
В самом деле, лично я так в середину массива элементы не вставляю. Вот пример из реального проекта, где я вставляю элемент в серёдку (при этом рост этих массивов у меня ещё и спрогнозирован и их «capacity» равняется удвоенному прогнозу):

    // если вставка требуется по индексу, который больше
    // массива, просто добавляем в конец
    if i >= len((*arr)[org]) {
        (*arr)[org] = append((*arr)[org], value)
    } else {
        // надо добавить любой элемент в конец, чтобы появилось место
        // если в срезе место есть, оно будет использовано автоматически
        (*arr)[org] = append((*arr)[org], nil)

        copy((*arr)[org][i+1:], (*arr)[org][i:])
        (*arr)[org][i] = value
    }
Если можно без кода, я могу привести примеры:
1. вставка строки в середину перечня товаров счёта;
2. вставка строки в середину перечня ролей пользователя;
3. вставка строки в середину перечня подзадач расписания;
Для таких штук существуют другие структуры данных: односвязный список, двухсвязный список, двунаправленная очередь.
Но как с ними обстоят дела в go, в котором нет обобщений. Ведь с ними работа тоже получается неудобной.
Для таких штук существуют другие структуры данных: односвязный список, двухсвязный список, двунаправленная очередь.

У этих «других штук» другие стоимости, что иногда может быть неудобно (Да, мне как-то была нужна упорядоченная структура с O(1)-доступом к произвольному элементу, и меня устраивало O(n) при ее расширении. Нет, кейс не помню, что-то из стандартных алгоритмов.)
Так думать надо, а иногда и бенчмарки делать, если не очень очевидно, какая операция наиболее часто делается.
Ну вот подумали. Провели алгоритмический анализ. Подтвердили его бенчмарком. Вышло, что массив и вставки в середину — эффективнее всего для данного случая.

От этого в Go появится операция insert?
lair, ваши комментарии заполонили каждую статью про Go. Предлагаю вам сделать следующий шаг и написать реальный проект на Go. Отлично будет, если это будет open-source проект — тогда мы вместе посчитаем, сколько раз вам понадобился insert или обход слайса в обратном порядке. Все таки главное разногласие у вас с Go именно в том, что практично, а что нет.

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

a = append(a[:pos], append([]T{x}, a[pos:]...)...)

Возможно даже прокомментировать код для ясности, если опыта в go не хватает для понимания того, что там происходит, и забыть эту операцию на следующие несколько лет.
Угу. И так k раз.
С n-ного раза захочется узнать, а что же там написано, а если знаешь, то конструкция выглядит вполне обыденно. Но, впрочем, ничего не стоит завернуть это в функцию и использовать k раз.

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

Вообще-то, я был одним из таких комментаторов.

И, к сожалению, это реальная жизнь.
Такова жизнь, но примеров из жизни никто так и не привел. Хотя мне еще тогда было интересно увидеть необходимость такой функции в серверном микросервисе на 100-200 строк, для создания которых и позиционирует себя golang.
Не, если go позиционирует себя только для таких микросервисов, то ладно.
Ну там примеры из жизни были — «я хочу написать вот именно такую функцию именно таким способом».

Ну а Golang себя не позиционирует, как язык для микросервисов — это, скорее, полезный побочный эффект, что маленькие сервисы писать удобно и легко и Go зачастую начинаются использовать в компаниях, с написания или переписывания отдельных сервисов. Как раз Go «позиционируется» для масштабов Google — большие кодовые базы, большие группы людей и т.д.
Вот и мы код с PHP на Go переписываем. Этот подход себя оправдывает. Сервисы показывают бОльшую производительность. Встроенная поддержка тестов позволяет делать код надежным и модифицируемым.
И все это в продакшене с миллионами пользователей.
Кто-то еще считает Go игрушкой, а кто-то уже сейчас получает от этого преимущество.
НЛО прилетело и опубликовало эту надпись здесь
Здесь T это как-раз тип, перепутать не получится, не скомпилится
Реальный код так будет выглядеть:

a = append(a[:pos], append([]string{x}, a[pos:]...)...)
НЛО прилетело и опубликовало эту надпись здесь
И мы снова возвращаемся к вопросу — Зачем?
НЛО прилетело и опубликовало эту надпись здесь
Go прекрасен!
Использую его уже более года, если что то и непонятно, то нужно лишь немного терпения (и умения читать, конечно) что бы разобраться!
В любом случае, не стоит недооценивать труд столь большой компании.
Вот я прочитал обе статьи и… немного не понял.
Вы так описали, что у меня сложилось довольно отрицательное впечатление о самом языке, причем именно от вашей статьи.
Половина аргументов выглядит «так делать нельзя, потому что так делать плохо.»
А вот если нужно, то пиши свой костыль и страдай.

Вы очень много пишите про дизайн Go и про то, что он такой удобный, но… на самом деле это нет.
Строгий язык не может быть удобным.
А язык, в основе которого лежат какие-то фиксированные практики программирования, которые говорят что «делать можно только так» тем более не может быть удобным.

Например, почему нужно писать так:
numbers = append(numbers[:2], append([]int{3}, numbers[2:]...)...)

Вместо того, что бы писать так:
numbers = append(numbers[:2], 3, numbers[2:]...)

Чем можно обосновать такое решение?

Или заменить int[]{3} на просто [3].

Присоединяюсь к мнению SirEdvin. Если статья «Почему Go это плохо продуманный язык программирования», воспринимается как «что мне не нравиться в Go, а нравиться в других языках».

То статья «Почему Go это хорошо продуманный язык программирования», воспринимается скорее как «Почему Go это хорошо продуманный плохой язык программирования»
Статья «Почему Go это плохо продуманный язык программирования» воспринимается как должна — молодежь тренируется писать статьи, выискивая противоречивые темы и не слишком основательно прорабатывает аргументацию, смещая акцент в эмоции. «Инженерный» троллинг :)

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

Серьезно?
Любой, кто писал на С/C++, знает во что превращаются проекты, после того, как кодом поработают 5-10 программистов, и код пройдет несколько стадий рефакторинга

писать несколько месяцев REST-бекенд на C++ и нанять для этого ещё 2 rock-star C++ программиста

и в Go, в отличие от, скажем С++, нет undefined behavior при сокрытии переменных

Все эти сравнения ( причем первые два — субъективные ) С++ с Go происходят, когда есть возможность показать, что Go лучше. При обратном сравнении приводится такая аргументация
Go — это другой язык, это не C++

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

Я бы Вашу характеристику отнес бы к обеим статьям
не слишком основательно прорабатывает аргументацию, смещая акцент в эмоции. «Инженерный» троллинг :)
НЛО прилетело и опубликовало эту надпись здесь
я всё ещё под впечатлением от рекомендации автором статьи использования связного списка для реализации сортированных массивов.

Добавление элемента в сортированный список.
Вы самостоятельно изменили слово «список» на «массив», и находитесь в шоке. Почему бы и другие слова не поменять, как вам хочется?
Ни о чём.
НЛО прилетело и опубликовало эту надпись здесь
Я попросил три реальных примера (показать код, к примеру или рассказать суть задачи).
Человек привел надуманный пример и сказал одно (сортированный список).
Вы перекрутили его слова, обвинив меня в том, что я предлагаю список для реализации сортированного массива.
Потом сказали, что «там как раз понятно».

Новый формат общения на Хабре, мда.
НЛО прилетело и опубликовало эту надпись здесь
сделайте тип, опишите правила сортировки, логику резервирования памяти, возможно вы будете не целый массив выделять, а например блоками для оптимизации операций вставки.
как мне поддерживать сортированной массив на C?
НЛО прилетело и опубликовало эту надпись здесь
Мало того, что вы мне вопросом на вопрос ответили. Так ещё и вопросы какие-то странные.
Ок, на C не получилось, давайте на C++
v.insert(upper_bound(v.begin(), v.end(), x), x);

— выполняет двоичный поиск и вставляет элемент.
НЛО прилетело и опубликовало эту надпись здесь
конкретно я про это:
> А почему на C, а не на C++?
я то конечно и попросил C т.к. там нет дженериков. В целом не сказать что приходилось прям сильно страдать от этого в Go (как-то либо стандартный sort, либо штуки на interface{}, либо совсем кастом) но реально они должны быть здесь (хотя бы для стандартных контейнеров).
кстати ваши примеры на 11 плюсах, которые через 20 лет вышли после первой версии
НЛО прилетело и опубликовало эту надпись здесь
C как бы это что-то старенькое.
Вообще это все ЯП, c++/c, go, python, haskell, php и т.п. и они все друг другу альтернативы.
> И что это нам говорит?
Нам это говорит что все развивается, где-то быстрее, где-то медленнее
> Кстати, конкретно этот пример на 14-х плюсах
в 11 добавили авто но не дописали что его можно использовать в лямбдах?

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

В плюсах нет встроенного параллелизма, сборщика мусора, а широкие возможности ООП по наследованию, виртуальным функциям и т.п. зачастую очень не плохо бьют по производительности.
И что мне теперь ржать в голос и говорить, что плюсы отстой?
Или вместо того чтобы сделать рабочий сервис за час, я буду сутки писать и дебажить его на плюсах лишь по тому что я не могу забабахать десяток шаблонных классов?
НЛО прилетело и опубликовало эту надпись здесь
> PHP — это альтернатива хаскелю и C++, ок.
Я вам написал подробнейшим образом, а вы не прониклись, да альтернатива, зависит от задачи.
Если вам нужно сделать сайт из пары страниц, не надо упираться и делать его на плюсах.

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

> Подумайте на досуге, почему вы спросили о сравнении с C, а не с ассемблером или Brainfuck или Whitespace.
Потому что я сам пишу на C и там нет generics. Подумайте на досуге, почему вы не смогли написать этот код.

> Есть (хотя кривой, не кривой делается на boost.asio один раз и почти на всю жизнь).

go func () {
// do
}()

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

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

> И GUI-библиотеки в самом языке нет.
опять сравнили теплое с пальцем.

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

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

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

Вы не ответили на вопрос.
НЛО прилетело и опубликовало эту надпись здесь
Нет, мой пример на C++98, самом первом стандарте.
Вы точно прочитали статью? Где в ней про удобство?

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

перейти на Go и написать все быстро и качественно

Возможно, я ошибаюсь, но мне кажется, что на неудобном языке быстро не напишешь.
Поэтому удобство подразумевается в данном контексте.
Раз пишется быстро то есть подозрение что все же достаточно удобен. Конечно же это не значит абсолютное удобство для всех и для любых задач.
На Basic тоже что-то пишется…
НЛО прилетело и опубликовало эту надпись здесь
Вы почему-то написали это в ответ на мой комментарий, так что отвечу.
1.
Распять мерзавца, как он посмел высказать свое мнение! Четвертовать его!

Лично Вам я поставил плюс.
2.
И внезапно язык становится неудобным во всем

Я этого не говорил. Прочитайте сообщение SirEdvin. В нем он спрашивает, почему некоторые моменты языка неудобны, чем вызваны данные решения создателей языка. Ему в ответ overmes пишет, что удобство языка нигде в статье не упоминается. И я отвечаю, что оно подразумевается во многих местах данной статьи.
3.
Я не преувеличу, если скажу, что немного разочарован в сообществе программистов. Более того, все эти кровавые холивары происходят по той же самой причине.

А мне кажется, что это как раз двигатель развития — аргументированный спор ( не путать с тупым флеймом! ). Программисты в душе — идеалисты. Хочется найти священный Грааль лаконичности, понятности и производительности. Вот и происходят споры, выявляющие плюсы и минусы каждого инструмента. Главное — не скатываться на личности и эмоции.
НЛО прилетело и опубликовало эту надпись здесь
> Написано, что Go помогает писать код с которым будет меньше проблем в будущем.
Это из области метеорологических прогнозов. Поживем — увидим. Предыдущим стремительно завоевывавшим рынок языком, с которым не будет проблем в будущем был КОБОЛ.

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

> Да и как удобный синтаксис может мне вдруг навредить завтра — тоже не очень ясно.
В общих чертах-то ясно. Плохой код должен выглядеть плохо. То есть идея в том, что глядя на вставку в середину массива, человек должен заподозрить неладное и убедиться, что оно к месту. Скажу за хаскель. Если бы писать там с мутабельными переменными было так же удобно, как без них, хаскель был бы другим. Вопрос только в том, что именно счесть плохим кодом, и вот тут да, мнения разнятся. Время покажет.
НЛО прилетело и опубликовало эту надпись здесь
А тут — набор ad-hoc-костылей и решений с потолка, уж простите.

Это не так. Хотите себя убеждать, что Go — это набор костылей с плохим дизайном, пожалуйста. Самообман — дело легкое.
Мне каждется, доказать то, что это обман достаточно просто, для этого все лишь нужно указать ссылки на статьи. Если язык не базируется на статьях, то можно попытаться агрументировать тем, что это хороший инженерный язык, и привести в доказательства рассылки и статьи в блог постах авторов, объясняющие решения, обосновывая это технически. К сожалению это будет доказательстов того, что язык построен на ad-hoc решениях (ну или костылях, смотря какая агрументация).
То есть идея в том, что глядя на вставку в середину массива, человек должен заподозрить неладное и убедиться, что оно к месту.

Именно так. Спасибо, хоть кто-то написал, что понимает о чем речь.
Это и вправду такая сложная концепция для понимания или я её непонятно объясняю?
Мне сложно сказать, потому что я понимал, о чем речь, до ваших объяснений, но, как мне кажется, основная претензия не к самому подходу «плохое должно выглядеть плохо», а к конкретному выбору того, что считать плохим. Ни в C++, ни в Хаскеле, ни много где ещё нет проблемы написать вставку в середину массива, т.е. если уж сильно надо, можно написать красиво. Это приводит реально к каким-то серьёзным проблемам? Если да, то было бы замечательно увидеть примеры и какую-либо статистику, а так это звучит несколько безапелляционно. Ну т.е. проблема в подаче и восприятии. Если подать как «авторы [языка] считают, что это решение оправдано», то это одно, а если «это будет хорошо в long term» без внятного ответа на вопрос «почему», то в купе с холиварным несколько стилем это и приводит к соответствующему стилю обсуждения.
Программисты на Го настолько тупы, что им нужно синтаксисом намекать на то, что вставка в середину массива — дорогостоящая операция.

Спасибо, теперь все встало на свои места.

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

Так «нужно» писать, потому что так писать не нужно. Если использовать неправильный инструмент, результат получается некрасивым (мягко говоря).

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

Правильно — увеличить размер слайса и сдвинуть все элементы на нужный offset и установить новый элемент (или несколько элементов):

s = append(s, 0)
copy(s[i+1:], s[i:])
s[i] = x
То есть, если мне нужно собрать в один массив несколько массивов и чисел мне тоже нужно будет так делать?

А как же синтаксический сахар?
Много сладкого вредно для здоровья :)

Если вам нужно собрать в один массив несколько массивов и чисел — вы сами решайте как вам это нужно сделать, в каком порядке и т.д. К вашим услугам append, make, и copy — вполне лаконичные и простые операции. Понять потом код очень просто.
Просто я не знаю Go, но разбираюсь по статье.
Я могу написать что-то похожее на:
append(arr1,1,arr2,3,arr4,5)

?
Нельзя, к сожалению. У append только одна реализация, которая проверяет тип при вставке.

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

Как то append<T'>(slice []T', e []T'|T'...) — сложновато…
Почему «к сожалению»? Сейчас append — детерминированная функция, которая делает одну ясную и четкую операцию.
Если вам нужно добавить несколько других значений и слайсов — сделайте это явно. Избавляйтесь от этого желания «написать все в два символа», чтобы потом другие программисты гадали, что же имелось ввиду и зачем.
То, что сложно для компилятора, не всегда сложно для человека. Смысл выражения append(arr1,1,arr2,3,arr4,5) вполне очевиден, особенно если функцию назвать join, а не append
А лучше так:

numbers = numbers[0..2] ~ 0 ~ numbers[2..$];
Тут уже спорный вопрос.
Я не уверен, что пойму, что делать операция ~, если увижу ее в незнакомом языке.
Тут же вроде за простоту сражаются.
Это конкатенация. Слово «append» тоже не говорит, что это соединение массивов, а не, например, добавление записей в файл :-)
Строгий язык не может быть удобным.

Конечно. Равно как и хорошим.
А если серьезно — язык должен быть удобным не для написания кода, а в первую очередь для его сопровождения. И тут строгость Go на вашей стороне. Потому что поддерживать код на Go — УДОБНО.
Правда я так и не увидел аргументов (т.е. конкретных примеров) как строгость делает язык неудобным. Следуя такой логике можно дойти до того, что JavaScript/PHP очень удобные языки. Удобнее Питона и тем более Java/C#. Но я бы не согласился с такими утверждениями.
Правда я так и не увидел аргументов (т.е. конкретных примеров) как строгость делает язык неудобным.

Все дело в ограничениях, которые накладывает на вас язык.
Подуймайте, какой костыль нужно будет соорудить, что бы написать, например, удобные матрицы на языке Go для различных типов данных. Сколько раз вам нужно будет просто копировать туда-сюда код? А теперь представьте, что вы еще добавили изменение в один тип матрицы, и вам нужно перенести их в другие…
Вы считаете, это удобно?
Следуя такой логике можно дойти до того, что JavaScript/PHP очень удобные языки. Удобнее Питона и тем более Java/C#. Но я бы не согласился с такими утверждениями.

Внезапно, но вроде как именно этот пункт выставляется одним из основных преимуществ Node.js для новичков.
Потому что писать различные веб-приложение на JavaScript или Python (серверную часть) куда проще и удобнее, а следовательно и быстрее, чем на Java/C#.
язык должен быть удобным не для написания кода, а в первую очередь для его сопровождения.

Это сложный дисскусионный вопрос. Что лучше, потратить больше времени на написание самого кода или на его review и комментирование?
А вы про какую строгость говорите?
Вроде как о наличии различных синтаксических соли и сахара.
То, что в языке нет generics — я тоже не считаю плюсом. Но это ничего не говорит про дизайн языка. Есть множество языков, где их нет, во многих они появились не сразу. Вполне возможно, что и в Go 2.0 (например) они таки будут.

Внезапно, но вроде как именно этот пункт выставляется одним из основных преимуществ Node.js для новичков.

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

проще и удобнее, а следовательно и быстрее

Быстрее «наговнокодить» имелось в виду? :)

Сопровождение — это не review и комментирование, а debugging и внесение серьезных изменений в приложение. А эти моменты — часто отнимают куда больше времени, нежели «первичное» написание кода.
И да — писать на Go быстро. Не так быстро как на Питоне, но сравнимо с Java/C# и быстрее, чем на C++.
То, что в языке нет generics — я тоже не считаю плюсом.

Как там фраза про «Язык уже закончен и развиваться не будет»?
Сопровождение — это не review и комментирование, а debugging и внесение серьезных изменений в приложение. А эти моменты — часто отнимают куда больше времени, нежели «первичное» написание кода.

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

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

Вот так никогда в реальности не бывает.
Если вы действительно заранее сели и на пару лет вперед хорошо продумали Архитектуру, то это значит только, что вы проели огромное денег бизнеса, впустую.
Архитектура — это то, что выстраивается в результате развития проекта. И она меняется и должна меняться. И вот эти изменения должны быть максимально простыми. Чего Go с успехом и добивается. А то, что в середину слайса вставить значение «не красиво выглядит» — в реальности на это всем плевать.
Так-так, что тут у нас сегодня? Ничего нового, в Go одни правильные решения, все пытаются делать из него питон и совать свои закоренелые паттерны. Ну, что я могу сказать? Хорошо.
По большей части я согласен скорее с вами, чем с автором оригинальной статьи. Кроме одного пункта — пункта 7.
Комментарии по определению это такие пометки, присутствие или отсутствие которых в коде не меняет поведения кода. Так во всех языках. Ну, разве что в Python встречаются любители хранить метаданные в docstring'ах, но их даже коллеги за это колотят. А тут вы говорите, что вызывать из комментариев кодогенератор — это норма. Кодогенератор, Карл! Да даже в C++ максросы сделаны лучше. А что, если этот комментарий сольётся с комментарием к функции ниже? В общем, можно сколько угодно защищать такое решение, ссылаясь на авторитет Пайка, но это реально выглядит на решение из разряда «да ну, для одного кейса не будем прагмы добавлять, сделаем магический комент и так сойдёт»
это машиночитаемый комментарий он автоматом ничего не вызывает, для него существует отдельная команда, которую надо запускать руками.
по смыслу — стандартизовали то, что уже использовали люди, только они это писали в make файлах или так же в комментариях: https://github.com/golang/net/blob/master/html/atom/gen.go.
Это чтобы например на основе описания protobuf сгенерировать исходный код на go и т.п.
Стандартизировать костыли — божественный подход к дизайну
эм, то есть автоматическая генерация кода в любой форме, это костыль?
вы уж определитесь к чему претензии к тому, что стандартизовали или как это сделали.

ну и в тему про магические комментарии:
https://github.com/golang/go/blob/master/src/runtime/wbfat.go#L6
https://github.com/golang/go/blob/master/src/runtime/wbfat_gen.go#L5
А тут изобретены аннотации, но почему-то не выделены явно синтаксически.
магические комментарии — это суть есть аннотации, как один из вариантов размещения неких метаданных в коде, чем "@NotNull" принципиально отличается от //go:nosplit или //go:generate?
Тем, что он
— не выглядит как комментарий
— обрабатывается не как комментарий

Аннотация явно говорит «тут делаются разные дела»
В случае комментария может быть так:

//go:generate toolname -params -blabla
//Hey! Look at my awesome function Blabla
//Lorem ipsum dolor sit amet, consectetur adipiscing elit.
//Donec tortor erat, rhoncus ac turpis id, ullamcorper congue odio
func Blabla() {
    // code...
}
вас смущает, что go doc зацепит этот комментарий к функции Blabla?
Меня, кстати, смущает.

(скажем, в C# просто комментарии и документационные комментарии отличаются)
не писал на c#, не могу сходу представить что вы имеете ввиду
public class SomeClass
{
  ///<summary>Это пойдет в документацию</summary>
  ///<remarks>И это пойдет в документацию</remarks>
  ///<param name="f">f-word</param>
  ///<returns>a swear based on <paramref name="f"/></returns>
  //а тут программист может писать что угодно, это не войдет ни в какую документацию
  public bool WhatThe(string f)
  {
  }
}


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

а есть вот такой
///Эта функция считает синусы


из комментариев второго типа генерируется документация, из комментариев первого — нет
аналог на go:
// это просто коммент

// а это информация о работе функции, она пойдет в godoc
func DoCool() {
}
он не пойдет в godoc — это приватная функция
Если я не ошибаюсь дока должна еще начинаться с названия метода?

// это просто коммент

// DoCool а это информация о работе функции, она пойдет в godoc
func DoCool() {
}
Это не норма. nosplit и noescape — это внутренности компилятора и рантайма, в реальном коде вы ничего подобного не пользуете. //go:generate, если уж понадобилось, вы пишете единожды в заголовке файла, а не где попало. Обсуждаемая выше проблема — чистой воды теоретизирование.
Обсуждаемая выше проблема — чистой воды теоретизирование

Как будто это делает решение поместить в комментарии инструкции для кодогенератора или «внутренности компилятора и рантайма» long-term хорошим решением.
А что, по вашему, будет хорошим решением?
Выделить это в отдельные сущности, как это было сделано во всех других языках?
Например, в аннотации.
Я, к примеру, не вижу плюсов от «введения новой сущности», зато ломается совместимость. Плодить новую сущность на каждый чих — это именно то, чем Go не является. Если хочется такого, то лучше выбирать другие языки. Если всё таки есть реальные проблемы с go generate или с комментариями — велкам в коммьюнити, выслушают, напишете пропозал, и ваше решение, раз оно реально лучше — имплементируют. Всё просто.
Я не знаю, как вы умудряетесь новой сущностью ломать совместимость, наверное вы избранный. Обычно она ломается, когда происходит наоборот.

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

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

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

Раз избранный, то поясню — новая сущность в Go 1.5 == ошибка компиляции в Go 1.4.
Не за что.

А это плохо.

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

Раз избранный, то поясню — новая сущность в Go 1.5 == ошибка компиляции в Go 1.4.

Эмм, а в Go правда считается нормальным компилировать код для поздних версий ранними компиляторами?
Раз избранный, то поясню — новая сущность в Go 1.5 == ошибка компиляции в Go 1.4.

Очень смешно звучит. То есть Go 1.5 совсем не добавляет ничего нового в сравнении с Go 1.4? Я вас правильно понял?

Главное навесить ярлык. Ясно, спасибо.

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

Лишить язык программирования возможности писать комментарии — это плохое решение.
То есть Go 1.5 совсем не добавляет ничего нового в сравнении с Go 1.4? Я вас правильно понял?

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

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

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

Лишить язык программирования возможности писать комментарии — это плохое решение.

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

Нет. Если совместимости все равно нет, тогда зачем вы к ней аппелируете?

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

Я говорил про комментарий. То, что он должен исходит из его определение.

Согласен. Только непонятно, про какой вы язык говорите.

Про Go, в котором комментарии были заменены на метаданные.
Нет. Если совместимости все равно нет, тогда зачем вы к ней аппелируете?

Я к ней аппелирую, потому что это один из моментов, по которым принимаются решения. Уже писал, что дизайн языка — это не черное и белое, и не бинарный выбор «очевидно, что это должно быть так» и «не так». Неужели это и вправду нужно разъяснять 15 комментариев подряд?

Я говорил про комментарий. То, что он должен исходит из его определение.

По определению самолёт — должен летать. Это не повод критиковать наличие шасси у самолёта. Это нужно и это удобно. Так же и тут.
Вам верность лингвистическому определению или практическая польза важна? Сколько вы пишете на Go, кстати?

Про Go, в котором комментарии были заменены на метаданные.

В Go не заменяли комментарии на метаданные.

Я к ней аппелирую, потому что это один из моментов, по которым принимаются решения. Уже писал, что дизайн языка — это не черное и белое, и не бинарный выбор «очевидно, что это должно быть так» и «не так». Неужели это и вправду нужно разъяснять 15 комментариев подряд?

А прямая совместимость бинарная. Она или есть, или ее нет. Как я понял, в Go ее нет. Смысла на ее ориентироваться нет, раз ее нет.
Вы просто привели бесполезный аргумент и все.
В Go не заменяли комментарии на метаданные.

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

По определению самолёт — должен летать.

В нашем случае, самолет совершает телепортацию, а не летает.

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

А вот и пошли аргументы в стиле «сначала добейся».

Чето все мелочи всякие обсуждаем. Может начать тему того, что в го отсутствует система управления зависимостями и намеченное решение выглядят как большой такой и страшный костыль, который все равно ее не решает. Такой то системный язык для больших команд и проектов. Благо хоть создатели осознают, что это большой фейл и надо с ним что-то делать. Жалко, что сами они не хотят с этим ничего делать.
А вот и пошли аргументы в стиле «сначала добейся».

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

Плохие практики в разных языках так же отлично решают свои задачи.
Например, что бы понимать, что generic в Java сделаны плохо, не обязательно иметь опыт работы с ней. Они объективно плохи.

Так же, как решение заменить комментарии на некую другую сущность.
Дизайн generics в java с type erasure оправдан. Реализация позволяет сохранить прямую и обратную совместимость с 1.4, что для enterprise-пользователей является очень существенным фактором.

Т. е. в библиотеку, написанную и скомпилированную под java 1.4 можно передавать generic-объекты из кода под 1.5 и наоборот.

То, что они могут быть субъективно плохи в ваших задачах не означает, что они плохи для всех. Так что никакой объективностью тут и не пахнет.
НЛО прилетело и опубликовало эту надпись здесь
Единственная причина, по которой их сделали именно так — недальновидность создателей первой версии Java.
Если пытаетесь намекать на дальновидность разработчиков .NET, который появился в 2000, то стоит посмотреть на то, что java появилась в 1995.

В C# generics появились тоже не сразу (2006, против 2004, когда они появились в java). И в случае .NET как-то не очень заморачивались совместимостью .NET 1.1 и 2.0.

У Java иной подход — сохранение совместимости. И во всех задачах, когда была необходимость использовать старый код в новом окружении (без какой-либо модификации и перекомпиляции) type erasure выигрывает по сравнению с переписыванием кода или запуском его различных кусков под разными версиями CLR.
Однако параметрический полиморфизм, то, что в java почему-то назвается Generics, (без подтипирования) появился аж в 1975 году, так что это не оправдание. Кстати, это же объясняет почему, в Go его нету, туда настолько молодые фичи не попадают.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Об этом я даже не подумал :)
В первую очередь меня смущает то, что может найтись чудак (особенно учитывая целевую аудиторию Go — тех, кого нужно «научить по-быстрому»), который напишет вот так:
//Hey! Look at my awesome function Blabla
//go:generate toolname -params -blabla
//Lorem ipsum dolor sit amet, consectetur adipiscing elit.
//Donec tortor erat, rhoncus ac turpis id, ullamcorper congue odio
func Blabla() {
    // code...
}


Ну прямо ОЧЕНЬ заметно, что тут аннотация в комментариях. В общем, в других языках, которые тоже компетентные люди проектируют, такие вещи выделяют в отдельные сущности, Пайк же посчитал, что это СЛОЖНО. Ну ок, я его понял, но по-моему технология для инженеров не должна ориентироваться на дебилов…
Если бы вы писали на Go, вы бы понимали, почему нет оснований полагать, что кто-нибудь так напишет. А если и напишет, то ничего страшного не произойдет. С таким же успехом можно говорить «Tesla — плохой автомобиль, потому что кто-то можно положить пальто на тачскрин и не сможет его видеть». Попробуйте на практике и судите о дизайне по делу, а не по придуманным кейсам.
Конкретно насчёт этого я сейчас немного разобрался и понимаю, что неправ.
Тем что это части синтаксиса языка.

Почему-то мало кто понимает, что «магические комментарии» в Go — это вообще не комментарии. go generate не парсит go-код, она тупо ищет подстроку. Посмотрите вот на такой код: http://play.golang.org/p/BwHvNiZggA — go generate найдёт тут свою инструкцию и попробует её исполнить, хотя она и не в комментарии.

Я люблю Go, но вот это конкретное место — это очень плохой дизайн. Имхо.
НЛО прилетело и опубликовало эту надпись здесь
TH это, кстати канонический пример костыля, т.к. радостно ломает абстракции (скрывает типы за ExpQ), в отличии от Generics, и даже появляющийся Typed-TH не очень поможет в силу ограничений. (Правда в отличии от generics позволяет генерировать более эффективный код, с расширениями generics такое тоже возможно, но уже не так просто). Естественно плюс TH, в отличии от, насколько я понимаю, go, в том, что генерация производится средствами языка, что не мешает вызывать внешние утилиты если необходимо. А совсем хороший вариант в MetaOcaml, например.
НЛО прилетело и опубликовало эту надпись здесь
Магические комментарии — это костыль. Претензии к тому, КАК сделали.
Лучший критический комментарий за два поста, imho.
«Костыль» — это ярлык, не более. Shebang — это тоже такой-же «костыль», что не мешаем ему исправно выполнять свою функцию на всех UNIX-системах, не так ли?
Так что важнее — практическая польза или чей-то ярлык «костыля»? Какие реальные практические проблемы с go generate были хотя бы у одного из комментаторов тут? Да ни у кого.

Конкретно по поводу go generate — был пропозал и были дискуссии о том, как лучше решить проблему. В дискуссии мог поучаствовать каждый хабровчанин и предложить «не костыль», обосновав, почему его «не костыль» будет хорошим дизайном.
Костыль, но имеющий четко определенное место. Он идёт первой строкой в самом начале файла. Его сложно не заметить и тем боле спутать с чем-то другим.
Аналогично другой костыль — указание кодировки файла для python 2. Тоже расположен в первой или второй строке и только там.
По сути дела они придумали препроцессор, но сделали вид, что они не при делах.
с make сравнили бы ещё ладно, но это не препроцессор
По факту ведь берется этот файл с магическими комментариями и на основе него генерируется другой, новый файл. Это ли не препроцессор в чистом виде?
При помощи make тоже можно препроцессор к любому языку программирования приделать.
По факту запускается любая команда, это как тоже самое, что сказать make или bash это препроцессор.
Эти запуски не как не связаны с процессом компиляции, в зависимостях которые вы ставите они не вызываются, только запуски руками.
Почитайте https://blog.golang.org/generate, возможно просто я плохо объясняю.
Ну просто получается, что необходимость в кодогенерации нужна, то есть по факту нужны обобщения, но их нет в языке и нет никакого стандарта на них.
Вот тебе и плата за простоту.
Не всё что решается генерацией можно решить обобщенным программированием. Примеры с генерацией парсеров и тп.
Думается мне, что такие вещи нужно решать через генераторы парсеров, которые вообще на другом языке написаны, специально для этого созданном, а не встраивать их в комментарии.
ну если вы начнете читать, что вам люди пишут может даже диалог получится.
//go:generate go tool yacc -o gopher.go -p parser gopher.y
как думаете что такое yacc?
yet another compiler compiler — генератор парсеров?
Отсюда:
Yacc is a computer program for the Unix operating system. The name is an acronym for «Yet Another Compiler Compiler». It is a LALR parser generator

НЛО прилетело и опубликовало эту надпись здесь
Ну вот Boost.Spirit обходится без препроцессоров.
НЛО прилетело и опубликовало эту надпись здесь
Видимо автор этой статьи знает и умеет в Go, но вот эти обиды, нападки на другие языки и «неверных» можно было бы и опустить.
Нападки на языки — это упоминание С++ в эпилоге?
По-видимому, Вы пропустили мой комментарий ( хотя это неудивительно, их тут уже 120+ ).
Просто все, кто писал на C++, переключившись на другие языки — изливают накопившуюся боль оттого, что столько лет провели на темной стороне силы :)
Я писал на C++, теперь на C++ и Haskell, но отчего-то боли не ощущаю :)
Go никому не нужен.
Программист C++ легко освоит его, это да.
Но в обратном я сомневаюсь.
Уместней было бы сказать «легче». Зачем вешать неуместные ярлыки на людей.
А по части нужности судить не вам думаю.
После того как меня «отхабрили» в предыдущем обсуждении Go, мне стало все равно.
Назвав собеседников хомячками вы чего-то другого ожидали?
НЛО прилетело и опубликовало эту надпись здесь
Это пост любви к Go, тут нельзя так грубо.
Эм, не стоит, тем более в выходной.
Может человек в Эмиратах живёт)
Тогда ему вдвойне хорошо)
НЛО прилетело и опубликовало эту надпись здесь
Статья же автора о том, что дизайн языка «плохой» — это, к сожалению, не более, чем попытка привлечь к себе внимание

Не берите на себя слишком много. Написали статью для самоуспокоения — замечательно. Но прошлая статья прекрасно описывала те проблемы, с которым, например, столкнулся я и долго плевался. И что-то подсказывает, что я далеко не один. Статья написана в том числе для привлечения внимания, но ее суть и основные тезисы описывают фактические проблемы языка, которые некоторые отказываются видеть и выдумывают тысячу отмазок вроде «так сделали, значит так надо и правильно», «это не нужно, приведите примеры, когда это нужно» и прочие попытки успокоить себя, не более того.
Я имел опыт общения с автором в последние несколько месяцев, и хорошо понимаю его мотивы. Поэтому предложения про «подростковый возраст» и про «попытку привлечь к себе внимание» — это не догадки.
Тем не менее, его статья поднимает актуальные проблемы. Мне не важно, какой у него внутренний мир
Вы это уже написали в 10 комментариях. Отсутствие отрицательных индексов — это не «актуальные проблемы», это «привычка». На этом и разойдемся.
Таки я угадал не имея опыта общения с автором. Как прочитал, себя вспомнил лет 15 назад :-D
Ну почему никто не пишет таких статей про C++? Там же на 100500 статей косяков наберется! Косяки Go — это мелкие шалости в сравнении с этим монстром!
Ну почему же никто? Из самого масштабного — www.yosefk.com/c++fqa. Просто в мире C++ в ответ на такие статьи выходят новые версии языка, а не ответные статьи в стиле «в языке этого нет, поэтому вам это не нужно».
Не смешите — проблема поддержки юникода возникла не вчера. В какой версии C++ стал из коробки поддерживать его?
Не знаю, в какой это появилось, но вроде бы wchar_t и wstring там есть очень давно.
Есть. Только поддержки unicode от этого не прибавляется.
Что тогда есть поддержка Unicode, если не возможность хранения и манипулирования unicode строками на уровне стандартной библиотеки? Да, там это не очень удобно делать, в основном из-за многочисленных устаревших API, которые умеют только char. Но все же есть.
Да ничего та нет. Ни конертации в локаль/UTF8 и обратно, ни поддержки работы с суррогатными парами. Есть «массив-байтов» (string) и «массив-непонятно-чего»(wstring)
Ни конертации в локаль/UTF8 и обратно

Насколько я помню, в стандартной библиотеке нет, но есть iconv
ни поддержки работы с суррогатными парами

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

Про второе, ну вот, например, смотрите, очевидно, что й и й — одна и та же буква, но на на самом деле это й и и&#774;. С++ это не поймет
А есть какой-то язык, который поймёт это из коробки?
Любой на платформе .net. Вот, скажем, F#:

> let s1 = "й";;
val s1 : string = "й"
> let s2 = "и\u0306";;
val s2 : string = "й"
> s1.Length;;
val it : int = 1
> s2.Length;;
val it : int = 2
> System.StringComparer.CurrentCulture.Equals(s1, s2);;
val it : bool = true
Понятно что библиотеки есть для всего. Речь именно про стандартную библиотеку языка, в которой это можно было бы удобно объединить со стандартным же IO.

Про второе, ну вот, например, смотрите, очевидно, что й и й — одна и та же буква, но на на самом деле это й и й. С++ это не поймет
Вы про collation? IO без разницы какой вариант нормализации вы применяете, выведет как есть.

Это ж не python2 у которого при выводе utf8 у танка отваливается башня, если вывод перенаправили/отправили в pipe.
Проблема в том, что IO как раз хорошо бы знать Потому что

(1) работать удобно с UTF-16, а пистаь/читать в файлы в UTF-8
(2) На некоторый системах (не будем показывать пальцем) консоль не понимает UTF, а понимает какой-ниюудь CP866

А при работе нужно чтобы поиск/замена понимали, что символ UTF8 может состоять из нескольких байт и даже слов UTF16
Работать с UTF-16 совсем неудобно. Он имеет все проблемы UTF-8 (символы имеют переменную длину).
Работать надо с настоящими code points. А любые кодировки — они для ввода-вывода только.
И поодержка этого кстати в C++ таки есть.
Ну хорошо, я согласен, будем считать, что я имел в виду «настоящие code points» :)

В С++ есть некоторый набор функций для этого, но это больше похоже на отмазку, чем на поддержку, потому что работать с этим неудобно. А некоторые вещи просто невозможно сделать платформонезависиммым способом.
А зачем при поиске и замене в UTF8 нужно знать, что символ может состоять из нескольких байт? Поиск и замена подстрок к этому нечувствительны.
Это хорошо пока вам не надо, например, делать case insensitive поиск/замену, где в бой вступает collation. Или замену символов с диакритикой из пользовательского ввода, где они могут быть как в decomposed так и в composed вариантах.
Да даже при обычном поиске встают вопросы. «ёлка» и «елка» — разные слова? Думаю, в других языках есть примеры похлеще.
чтобы вот это работало, например

#include <iostream>
#include <string>

int main() {
    std::string s {"пр?вет, мир"};
    s[s.find('?')] = 'и';
    std::cout << s << '\n';
}
Достаточно искать и вставлять подстроки, а не символы, тогда будет работать
Суперинтуитивно!

А по факту тип char и string::operator[] не работают
А они где-то работают? Например лигатура ае может быть как одной, так и двумя буквами в зависимости от языка. И как взять в слове vae третью букву?
А они где-то работают?

Угу.

> let s1 = "vae";;
val s1 : string = "vae"
> let s2 = "v\u00e6";;
val s2 : string = "væ"

> System.StringComparer.InvariantCulture.Equals(s1, s2);;
val it : bool = true
> System.StringComparer.Ordinal.Equals(s1, s2);;
val it : bool = false


И как взять в слове vae третью букву?

> s1.[2];;
val it : char = 'e'
> s2.[2];;
System.IndexOutOfRangeException: Index was outside the bounds of the array.
Во втором примере вы показали, что оно — не работает, а про сравнение я и не спрашивал.
Знаете, мне кажется, что это упирается в требование к «работает». С моей точки зрения, семантика (различная!) обоих типов (и строк, и символов) передана верно.

PS Я, заметим, не говорю, что в других языках сделано неправильно или хуже, я про это мало что знаю.
Я ссылался на этот комментарий.
Ну, как раз проблема «символ может состоять из нескольких байт» в моем примере успешно решена: адресация внутри [] идет посимвольно. а не побайтно.
Как раз нет. Обе эти строки — одно и то же слово, и в нём одна и та же третья буква — «e». А вот если взять другой язык, где есть буква "æ", то это будут разные слова, а посему операция взятия n-ой буквы должна ещё и культуру принимать.
æ — это две буквы (или одна, смотря какой язык), но code point в данном случае — один, хотя опять же, ту же «й» можно выразить двумя code point'ами. Операция индексации ж должна корректно взять третью букву в слове «май», даже если «й» там из двух «символов».
Обе эти строки — одно и то же слово, и в нём одна и та же третья буква — «e».

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

Вот с «й» сложнее — там действительно всегда одна буква, вне зависимости от количества char'ов, но я не знаю, как так правильно реализовать, чтобы при этом можно было и с бреветами отдельно работать.
Ну, собственно, я то и не спорю. Я как раз спорю с тем, что интуитивный способ работы хорош, ибо тут как раз абстракции протекают.
С чем работать удобнее — зависит от приложения. Иногда удобнее с utf8, иногда с utf32, иногда с utf16, а иногда и с bocu1. IO не должно это ограничивать.

В той же java есть два слоя io: input/output streams (или *channel+*buffer, если говорить про nio), которые оперируют байтами, и reader/writer, которые оперируют символами, кодируемыми в соответствии с параметрами конкретного reader/writer.

Про legacy-систему, где консоль «типа» 866, а на самом деле — смесь 866 и 1251 (параметры в argv передаются в cp1251) лучше постараться забыть, как страшный сон =)

А при работе нужно чтобы поиск/замена понимали, что символ UTF8 может состоять из нескольких байт и даже слов UTF16
Это вопрос к используемому вами движку regexp. Он не обязательно входит в стандартную библиотеку. И не обязательно одинаков между системами в том случае, когда входит в неё.

Что означает «символ UTF8 может состоять из нескольких байт и даже слов UTF16» мне не понятно. Набор codepoint'ов может быть представлен в utf8, utf16le или utf16le. Если есть CP от U+10000 до U+10ffff, то он будет представлен в виде суррогата в utf16 и в виде 4 байт в utf8.
Про legacy-систему, где консоль «типа» 866, а на самом деле — смесь 866 и 1251 (параметры в argv передаются в cp1251) лучше постараться забыть, как страшный сон =)
Суть в том, что страшным сном оно становится как раз из-за того, что в C++ нет нормальной поддержки строк, которая бы брала всю работу по конвертации на себя.

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

Это вопрос к используемому вами движку regexp. Он не обязательно входит в стандартную библиотеку.
Я даже не про regex. Но он, кстати, сейчас входит в стандартную библиотеку.

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

Независимо от поддержки unicode программой, изменить кодировку консоли вроде бы нереально. И как прикажете писать в консоль с cp866 произвольные символы?

Хотя преобразвание utf кодировок для строк при выводе в нормальную консоль из коробки было бы к месту.
Во-первых, как минимум можно корректно все парсить всегда в одну кодировку независимо от текущей локали (argv, std::cin)

С выводом, конечно, будут проблемы. Как минимум имело бы смысл выводить в UTF-8, если вывод редиректится куда-то, и, возможно, вопросики, если вывести на консоль символ не получается.
Если речь про cmd, то всегда можно использовать chcp 65001, если сменить в свойствах консоли шрифт. UTF8 батч файлы начинают говорить на разных языках.
Штука полезная, запомню. Интересно, что она внутри использует. Можно то же самое делать внутри своих программ. А то всех пользоваться данной командой не заставишь.
SetConsoleOutputCP
В C++11 добавили char16_t, char32_t и u16string, u32string как альтернативу «непонятно чему» wchar_t и wstring, а также <codecvt> в целом и codecvt_utf8 в частности для конвертации, включая суррогатные пары.
суррогатные пары
Суррогаты есть только в utf16, т. к. не всякий codepoint может быть представлен одним uint16. В utf8 этой проблемы нет.
Возможно, вы имели ввиду не суррогатные пары, а формы нормализации (всякие NCD/NFC/NFKD/NFKC).
Я имел в виду конвертацию UTF8 -> UTF16 и наоборот, где с суррогатными парами приходится разбираться.
Возможно, вы имели ввиду не суррогатные пары, а формы нормализации
Скорее, я имел это в виду. Спасибо.
Ок, простой тест

#include <iostream>
int main() {
std::cout << "привет, мир\n";
}

уже работает на всех системах одинаково, печатая «првиет, мир»?
Ну да, копирует на stdout строку в той же кодировке, в которой она введена в исходнике. (Если вы намекаете на виндовую консоль с её legacy cp866 — перенаправьте вывод в файл.) Для этого поддержка unicode не нужна вообще.
Отлчино. Проблема в том, что это самый просто пример того, где наглядно демонстрируется то, что C++ работает не со строками, а с массивами байт. Взяли массив байт и отправили на stdout, как вы и говорите.
Эм. А чего вы хотели, сказав просто отправить массив байт в поток? Хотите конвертации по дороге — так и говорите:
#include <iostream>
#include <locale>
#include <codecvt>
int main() {
    // вариант 1: просто конвертируем строку wchar_t -> utf8
    std::cout << std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(L"привет, мир\n");
    // вариант 2: объясняем потоку, чтобы он конвертировал wchar_t -> utf8 при выводе
    std::wcout.imbue(std::locale(std::wcout.getloc(), new std::codecvt_utf8<wchar_t>()));
    std::wcout << L"привет, мир\n";
}
1) Я не хочу ничего говорить, я хочу, чтоб строка текста выводилась как текст. Всякие кодировки оставьте в прошлом веке.
2) Я не хочу конвертировать в utf8, я хочу чтобы строка выводилась строкой и на Linux, и в Windows, и на светодиодном табло.
А я наоборот хочу работать с байтами.

С++ как раз такой язык который делает ровно то что попросили. Нужна определённая кодировка — попросите об этом. Нужны байты — будут байты.
Ну вот я прошу кодировку «чтоб было читаемо независимо от того, куда идет вывод и на какой системе». Как?
Я не хочу ничего говорить, я хочу, чтоб строка текста выводилась как текст. Всякие кодировки оставьте в прошлом веке
так вроде только вот совсем относительно недавно начали понимать что важно знать кодировку применительно к строке, иначе зоопарк выходит как в прошлом веке.
1) Я не хочу ничего говорить, я хочу, чтоб строка текста выводилась как текст. Всякие кодировки оставьте в прошлом веке.
В какой кодировке? Текста без кодировки не существует. Строка — суть просто набор байтов.

Ну вот я прошу кодировку «чтоб было читаемо независимо от того, куда идет вывод и на какой системе». Как?
Utf-8?
Ещё хуже, т. к. представление одного и того же текста (как упорядоченного набора глифов) не единственно даже в рамках одной кодировки.
Строка — суть просто набор байтов.
Нет. Строка — суть кусок текста. То, что вы там напридумывали — это все от бедности. Строка не может быть «просто набором байтов» хотя бы потому, что строкам и тексту уже тысячи лет, а эти ваши байты вот только придумали.
Ну числа это тоже числа, однако в памяти это наборы байтов в определенном порядке. И знать little или big endian это надо, если хочется, чтобы вывелось правильно везде. Тут тоже самое. Текста в понятиях ПК не существует. Есть текст — суть, байты, которые в определенной кодировке дают текст на экране. А в другой уже не дают. Без кодировка нет текста, будь это UTF или даже просто ASCII. И я не видел ниодного рантайма, который бы не упоминал этих понятий. Просто напросто невозможно в полной мере манипулировать байтами, когда кодировка их содержимого неизвестна.
Нет, числа — это числа. И знать про little или big endian нужно только в качестве разминки для ума, но для проведения вычислений эти знания не требуются — спросите любого бухгалтера.

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

Понимаете ли, есть разные слои абстракций. little или big endian нужны, если вы разработчик сериализатора. Если вы только используете сериализтиор, то вам это совершенно не нужно. Знать про особенности представления строк нужно, если вы разрабатываете поддержку Unicode. Но если вы заставляете меня, как пользователя вашей библиотеки по работе с Unicode с этим разбираться — то вы плохой разработчик библиотеки для поддержки Unicode.
Да чего о строках говорить, когда у нас и чисел-то нет нормальных :)
Да с числами вообще беда! Попробуйте-ка посчитать 42! на С++, напрмиер
> строкам и тексту уже тысячи лет
Строкам-то да, а вот компьютерам нет. А компьютеры неявно тут очень даже подразумеваются:

> чтоб было читаемо независимо от того, куда идет вывод и на какой системе
Вы ж не про пергамент и не про надписи на стенах, а про компьютеры.
То, что с компьютером все гораздо сложнее, чем с пергаментом, говорит не в пользу компьютера, не так ли?
Так уж и всё?
Символы же в компьютер вводят не в виде набора бит. Нажимают кнопку с определенным символом, или касаются области экрана с изабраженным на нем символом, или вводят пером и распознается символ. Набор символов — текст. И вводят именного его. И обычно хотят чтобы при всех преобразованиях он оставался текстом и выводился обратно(на экран, принтер и тд) именно в виде того же набора символов(ну или чуть измененного нужным образом). Поэтому подробности хранения текста для пользователя сугубо вторичны. Он на более высоком уровне оперирует и опускается до кодировок только от безысходности или при разработки интерфейсов обмена данными в двоичном виде. Поэтому в идеале есть строка текста(в какой-то фиксированной, известной рантайму языка или компилятору кодировке) и пользователь просит вывести эту строку в консоль. Вывестись в идеале должна именно эта строка, причем без дополнительных телодвижения со стороны пользователя. Рантайм может узнать в какой кодировке консоль ожидает данные и сам перемять в нужное представление. Уровень взаимодействия в данном случае — «выести строку текста с помощью устройства», а не «отправить массив байт в устройство». Уровень массива байт тоже нужен, он должен быть доступен на случай необходимости полного контроля, но это нижний уровень. И всё время на нем оперировать это скорее привычка от плохой жизни.
Lol4t0,
Нет. Строка — суть кусок текста. То, что вы там напридумывали — это все от бедности. Строка не может быть «просто набором байтов» хотя бы потому, что строкам и тексту уже тысячи лет, а эти ваши байты вот только придумали.
Понимаете какая штука… Компьютеры оперируют только битами, в оперативной памяти нет никаких букв, текстов и строк, там и чисел-то так таковых нет. Даже чтобы получить обыкновенный int и то нужно знать сугубо вторичную для пользователя вещь: хранится ли это число в little-endian или big-endian. Считайте это «кодировкой» чисел. Если вы не знаете «кодировку», вы не сможете интерпретировать биты в виде числа.

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

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

И знать про little или big endian нужно только в качестве разминки для ума, но для проведения вычислений эти знания не требуются — спросите любого бухгалтера.
Вот тут и настаёт привет: пока числа на бумажке у бухгалтера, у них действительно нет никаких little- и bin-endian. Но это представление появляется, как только числа набирают кнопочками на клавиатуре.

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

С остальным, про идеальные строки и взаимодействие с пользователем, я согласен. Но C++ так не работает, он плюётся байтами.
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!):
The Single Most Important Fact About Encodings

If you completely forget everything I just explained, please remember one extremely important fact. It does not make sense to have a string without knowing what encoding it uses. You can no longer stick your head in the sand and pretend that «plain» text is ASCII.

There Ain't No Such Thing As Plain Text.

If you have a string, in memory, in a file, or in an email message, you have to know what encoding it is in or you cannot interpret it or display it to users correctly.
Понимаете ли какая штука… Природа оперирует только атомами, в природе нет никаких битов, байтов и кодировок, там и оперативной памяти как таковой нет.
Я-то согласен, но те же рассуждения применимы и к обычным числам, где приходится почему-то знать, сколько там байт внутри. Но много ли где умолчальный Int — безразмерен? А float/double?
Ну да, умолчание в C++ — это дефолтная локаль, которая не факт что utf8 (особенно в случае с windows).
Потому что плюсовики не замусоривают хабр статьями с восхвалениями своего инструмента.
Первой появилась статья негативная. А эта не восхваление, а восстановление статус кво.
Зато до этого большинство статей только о том, какой это прекрасный язык. Как это обычно бывает со всеми новыми IT игрушками. Тот же docker какой прекрасный распрекрасный нам рисовали все время. NoSQL как нам рисовали, помнится. Правильно люди на конференциях Go говорят — перед знакомством с языком надо опустить свои ожидания, которые из-за хайпа вокруг него завышены очень сильно. Тогда язык не будет казаться непонятной хренью непонятно для чего.
Далеко не первой.
Забавно, что отсутствие отрицательных индексов избавит вас от страшных багов, а несовсем-нулевые-интерйесы — мощнейшая технология, которую надо просто выучить.
Поэтому нужно переходить на Раст и никаких вам недостатков.
Радуюсь ежедневно.
Мы рады, что вы радуетесь, а можно аргументировать? Почему это «поэтому»? Недостатки есть везде, нет ничего идеального.
Я использую силу плюсов других хабравчан за доказательство!
НЛО прилетело и опубликовало эту надпись здесь
Из за Go меня отхабрили. Ненавижу Go.
Теперь хочу посвятить жизнь написанию гневных публикаций против Go.
Обида живет в груди глупых
Вы правы. Не стоит обижаться на хомячков.
Go не нужен.
Почему?
Asm все равно быстрее…
Ну хватит уже…
НЛО прилетело и опубликовало эту надпись здесь
http://play.golang.org/p/9xjT-oHxfI
НЛО прилетело и опубликовало эту надпись здесь
Проблема в том, что скрывается за функцией «reversed» и какие операции оно выполняет :)
И в итоге все становится на свои места.
Я боюсь, что проблема в том, что в питоне можно написать одну функцию reversed и пользоваться ей, а вот в Go — только если авторы языка подарили.
Только вот разница описанного мной подхода и с использованием «reversed» скрывается в алгоритмической сложности.
А вы готовы утверждать, что невозможно написать такую реализацию reversed, которая будет иметь алгоритмическую сложность, сопоставимую с простым обходом массива?

(вам продемонстировать? не на питоне, правда)
reversed(items) возвращает итератор:
>>> x = [1, 2, 3, 4]
>>> reversed(x)
<list_reverseiterator object at 0x10092c668>

который, судя по названию, делает то же самое, что цикл с убывающим индексом, только удобнее. Поэтому в алгоритмической сложности разницы нет вообще.
Спасибо за уточнение, аргумент вполне себе.
Вот я тебя и вычислил, nyarum!
Го ориентирован на скорость работы. В го вы тоже можете написать функцию которая вернет список обратный заданному… но это копирование памяти которого можно избежать. Поэтому приходится больше кода как плату за скорость работы.
НЛО прилетело и опубликовало эту надпись здесь
В го вы тоже можете написать функцию которая вернет список обратный заданному… но это копирование памяти которого можно избежать.

(1) эта функция, как неоднократно обсуждалось, не может быть универсальной
(2) некоторые языки, внезапно, позволяют это сделать без копирования
Обратный обход можно записать несколько проще: http://play.golang.org/p/Ij9XjQQixz. Да, не reversed, но.
НЛО прилетело и опубликовало эту надпись здесь
В котором практически отсутствует смысл в отсутствии дженериков, которые, как известно, нинужны. Х)
Интент теряется, к сожалению. Хотя визуально элегантно.
даже в C++ можно сделать
for (auto i : boost::adaptors::reverse(x)) {
    ;;
}
НЛО прилетело и опубликовало эту надпись здесь
Так же как в си
Это было убрано намеренно, потому что выражение s[i:j] может молча дать неверный результат, если j станет меньше нуля.
Выражение s[i:j] может молча дать неверный результат, если i или j станет не тем положительным числом, о котором думает программист, представляете! И то, что j станет вдруг отрицательным после того как было положительным ещё менее вероятно, и это, скорее всего, будет уже совсем другая проблема.

Никаких веских аргументов в защиту Go вы по факту не представили. Вы просто повторяете мантру, что в Go всё великолепно, а всё, что называют недостатками — это на самом деле достоинства в долгой перспективе. И всё это так, потому что всё это держится на колоссальном опыте и авторитете Роба Пайка. Вы случайно не подрабатываете евангелистом Go в Google на полставки: ?)

Если что, то я ни в том и ни в другом лагере, просто высказал свои впечатления от статьи.
Идея не в том, что s[i:j] может что-то неправильно вернуть. Идея в том, что автор первой статьи никак не проанализировал существующую аргументацию, а просто ограничился демонстрацией и безапелляционным «плохо». И даже не просто плохо, а «прикиньте, они вот так делают, вот дурачки». Что толстый вброс :) Вторая статья — это уже шаг вперед.
Я не знаю, что для вас будет «веским аргументом». Авторы явно дают понять — на нашем опыте (не забываем, что это 50+ лет, создание UNIX, B, UTF-8 и тд), минусовый индекс приводит к реальным сложноуловимым багам. Что здесь должно служить «веским доказательством»?

Вы случайно не подрабатываете евангелистом Go в Google на полставки: ?)

К сожалению, нет :) Но подход Go слишком refreshing после языков, стремящихся за фишками и возможности сделать всё что угодно любыми способами, и приводящих к тоннам багов и ужасного неподдерживаемого кода в дикой природе.
А Go нет никакой возможности нам еще доказать, что он чем-то лучше этих языков «приводящих к тоннам багов и ужасного неподдерживаемого кода в дикой природе». Go новомодная штучка, все его достоинства пока что существуют в большинстве на словах и в мечтах авторов некоторых статей. Когда дорастет, то приходите, обсудим, во что превратился некогда такой прекрасный язык.
Данный комментарий — гипетрофированный пример альтернативной точки зрения, но к минусам я готов.
50+ лет

создание UNIX

Ну да, наигрались с адресной арифметикой и решили запилить чего по-безопаснее, а вот посмотреть, что вокруг появилось — не хотели или забыли? Лямбды? Ну это в 80-е тупило, ну и сейчас тупит, да и всю жизнь без этого пишем, ненужно. Почему в Rust смогли сделать и удобно и быстро, а в Go — нет? Новички, говорите, не осилят? А может, их тогда вообще рановато до продакшена допускать? Технология для инженеров не должна ориентироваться на дебилов.
В общем это… Может быть, авторам на пенсию пора?
В конце концов не забываем принцип Питера
В иерархической системе каждый индивидуум имеет тенденцию подняться до уровня своей некомпетентности

Всю жизнь косячили с отрицательными индексами, а теперь диктуют всем что это опасно, приводит к багам и НИНУЖНО

И это всё я пишу лишь к тому, что авторитет, каким бы он не был, это для разумного человека ещё не довод принимать мнение этого авторитета без аргументов.
Я видел код на Rust — это новый C++. Т.е. про удобство — это не в кассу.
Самое большое зло Go, это не косяки в языке, а его комьюнити. Такого количества слепо наяривающих на своего любимчика фанбоев, нету даже у JS.
Угу и благодаря этому комьюнити на Go сейчас создаются или переписывается довольно таки большое количество проектов. Не надо переходить на личности, это как минимум не культурно.
з.ы.Недавно узнал что в SpaceX используют Go.
Да что Вы тролля кормите :)
НЛО прилетело и опубликовало эту надпись здесь
Про С++ когда-нибудь слышали? Ваш Go еще из пеленок не вырос. Все еще на стадии «а что же это за зверь такой»
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Так в том-то и дело, что вы не просто пишете на go, вы вдобавок пишете статьи о том, как пишете на го. А вот это уже непростительно!
</irony>
Мне кажется это, как тут уже говорили, имидж языка, который вот такими статьями и создается. Язык вроде и не плох, и есть чем ему похвастать против остальных, но вот такое вот комьюнити создает враждебную атмосферу, когда уже на любых защитников языка кидаются с уверенностью, что это наверняка очередной фанатик, который дальше своего Go видеть разучился, аргументов внятных предоставить не может кроме «Пайк сделал, значит правильно». И ведь много таких в комментариях даже здесь. Напротив, хейтерства именно я вижу мало. Я вижу людей, которые обсуждают то, что им не нравится. А против них обычно фанатик, который внятно свою позицию обозначить не может. Просто слепая вера какая-то в святость путей, избранных Go.
А можно пример, где в C++ undefined behavior от сокрытия переменных? Что-то не могу придумать
Тоже сходу не понял. А суть вот в этом случае.
Ну, я не согласен, что тут дело в сокрытии переменных. Если убрать внешний int x, ничего не поменяется.
Отлично, спасибо за практичный разбор. По многим пунктам согласен.

for number := range numbers {}


number тут будет индекс (если numbers is slice)
я пишу на GO и мне нравится. да есть некоторые вредные моменты в языке, но и что? кто тут знает идеальный язык? Можно взять любой язык программирование и сказать что он ужасный потому что в нем…
я вам могу написать на каждые язык программирование статью
«Почему %язык X% плохо продуманный язык программирования». Может хватит тратить килобайты сети на лишним срачку про GO. Язык как язык. Он родился и вырос себя показал и останется. Как и других языков у него будет своя ниша и свой процент кода в мире.
А вы знаете много языков, которые продвигают как идеально спроектированные?
А вот автор статьи явно считает, что Go идеально спроектирован профессионалами, а остальные
студентами-любителями в порыве написать что-нибудь свое
не остальные, а «многие другие» — что правда :)
А я не думаю что GO идеальный язык я просто его использую для подходящих задач. А то что GO спроектирован профессионалами тут спора нет
Э б не был бы так уверен… я не видел еще не одного профессионала в проектировании языков.
Вместо Э должно быть Я, вместо не должно быть ни :(
Вы явно не профессионал в проектирования языков :)
А вот автор статьи явно считает, что Go идеально спроектирован профессионалами

Автор статьи уже несколько раз писал, что категориями «идеально»/«не идеально» не мыслит. Не нужно обвинять его в том, что придумали сами. :)

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

Есть апи которое работает с неким ресурсом:
package core
type KernelAPI interface {
...
LoadDump(fileName string) error
...
}

есть модуль импорта в данный ресурс сторонних форматов назовем его импортер, который использует KernelAPI

package importer
import "core"

type Importer interface {
ImportCSV(kernel *KernelAPI)
}


но приходит день когда вместо LoadDump нужен hotfix который должен использовать Importer. это противоречило логике проекта и более того нужно было только для игр, но нужен был именно короткий хак для теста того что там Importerы нагенерили ( к core — привязан веб с кучей отчетов и возможностью просмотра данных). Как решение надо было разделять имплементацию и АPI — что повторюсь само по себе не плохо но данный рефакторинг был значительно больше данного временного хака.
сам попался на такое ограничение
немного подумал посмотрел на свою реализацию
разрешил циклические ссылки
архитектура приложения только выиграла от этого ИМХО

так что может это не такой уж и большой порок

Знаете, когда я слышу, что у кого-то есть циклическая зависимость — я сразу понимаю, что архитектура приложения плохая. Просто по опыту. Иногда приходилось серьезно рефакторить приложение из-за таких зависимостей, но в результате всегда улучшалась архитектура. Это просто эмпирическое правило.
Почему Go — плохо продуманный автомобиль?
1. Коробка переключения передач — в бардачке.
2. Тормоз — не всегда тормоз.
3. Забавно работают поворотники.
4. Ты не можешь просто взять и залить воду в бачок омывателя.
5. Неочевидная логика использования ремней безопасности.
6. Сомнительная строгость сигнализации и противоугонной системы.
7. Квадратные колёса — это просто костыль.

И да, чувак, который это придумал — немного не в себе.

НИФИГА! Go это хорошо продуманный автомобиль. Потому что:

0. Оставим в стороне наезд на чувака. Теперь о деле.
1. Неопытные водители часто включают не ту передачу. Именно так мы похерили новенькую коробку на прошлых выходных, когда друг врубил заднюю на трассе. И тут Его посетила мысль — а давайте чтобы водилы реже ошибались, уберём нафиг этот рычак в бардачок. Пока он туда тянется, он успеет несколько раз подумать и наверняка уж не ошибётся. И хватит уже сравнивать Go с BWM.
2. Обожаю этот момент. В мануле чётко сказано, что тормоз — это не всегда тормоз. А если ты не прочитал мануал, ты сам тормоз. И это великолепное достоинство Go, в отличие от других поделок.
3. Они работают так как должны. Да, немного непривычно их включать, да, они не выключаются автоматически, да они мигают разными цветами (а иногда не мигают). Но вы должны привыкнуть. Потому что это правильно. Вот увидите, вас и вашу люстру будут пропускать везде!
4. У меня тоже сначала не получалось. Но потом я выяснил, что обычная вода не подходит, нужен легкий раствор соды. И чистит лучше! И да, если ты не прочитал об этом в первый же вечер в мануале, ты снова тормоз.
5. Если ты плохо выспался, или ты просто тормоз, то естественно эта логика покажется тебе неочевидной. Короче, Go — это не Мерседес тоже. А ты — тормоз. Учи мануал.
6. У тебя ещё ничего не угоняли? А вот у меня угоняли. Поэтому рядом с моим Go всегда дежурит наряд полиции, к машине подпускают строго по паспорту, конвой, все дела. У тебя ещё просто ничего не угоняли.
7. Есть огромная пропасть между водилами-теоретиками и водилами-практиками. Практики знают, что с квадратными колёсами гораздо проще удержать автомобиль на наклонной плоскости. Все остальные — тормоза.

— Стёб на стёбе, конечно. Но если убрать шелуху, то всё выглядит именно так. И с языком, и с его комьюнити, и с этими двумя статьями.
Аналогия интересная, но явный перекос в мануальный негатив :) Не забывайте, что перед эксплуатацией автомобиля на дороге нужно сдать на права.
Права в данном случае это теоретические аспекты программирования и практический опыт на каком-либо языке (паскаль в основном, наверное). Вы же не сдаёте на права при покупке нового автомобиля всякий раз? :)
Ну если ездил на коробке автомат, то поучить как себя ведет машина с ручной коробкой будет не лишним.
Это просто пять, схоронил.
НЛО прилетело и опубликовало эту надпись здесь
Э не. Я сел в автомобиль, мне не понравилось, и я рассказал об этом остальным. А вы почему-то воспринимаете критику языка на свой счет.
НЛО прилетело и опубликовало эту надпись здесь
Ситуация как раз обратная. За вами никто не бегает. Вот написал человек статью. Мол, не понравился мне язык — потому что первое второе третье…
А автор этой статьи начинает ему доказывать — все так как надо, и так должно всем нравится, а вот у других как раз плохо. Так кто за кем гонится? И кто не обращает внимания? Появилась бы эта статья, если бы никто не обращал никакого внимания?
Отнюдь, статья была не «мне не понравился язык», а «какой плохой дизайн у языка». Статья, которую, не читая, репостят и рассылают, а комментарии оккупированы людьми, не знакомым с языком, но люто его ненавидящим, и искажающим реальную картинку. Эта статья — зеркальный ответ для уравновешивания, не более.
НЛО прилетело и опубликовало эту надпись здесь
Ну знаете.
Мне больше кажется, что у большинства иначе:
1) Нельзя залить бензин из салона? Фу, отстой, в моем автомобиле можно! Поэтому он лучше!
2) Колеса всегда должны быть одинакового диаметра? Неуниверсально!
3) Дворниками нельзя чистить капот? В топку!
4) Фары не могут светить в салон? Как вы этим убожеством пользуетесь?
5) А вот мое авто еще летать может, правда меня уже 2 раза за это чуть не посадили. Но без этого — отстой!
6)…
Обсуждения вокруг Go, по крайней мере, в исполнении некоторых людей, всегда удивляли меня количеством аргументов ad hominem. Давайте просто пройдемся по этому посту:

авторы Go, исходя из своего, более чем, полувекового опыта разработки, видят [...] Решение, [...] уменьшающее риск хитрых ошибок в long term. Понятно, что не все мыслят на long term, отсюда и конфьюз.


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


пропасть, между программистами-практиками и программистами-теоретиками [здесь к ним причислен программист из Mozilla, ага].


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


Мне, если честно, всегда намного больше импонировал подход Липперта, который в ответ на каждый вопрос о той или иной фиче в C# приводил конкретные примеры, где, как и почему это работает, не работает, приводит к проблемам, удаляет проблемы и так далее. И не стесняется сказать «да, это ошибка дизайна, и мы теперь вынуждены с ней жить, потому что мы не готовы ломать обратную совместимость».
Не думаю, что Роб Пайк стесняется сказать что-то подобное :) Просто он в авторы двух рассматриваемых статей не входит, как не входят и многие другие разработчики Go.
А имидж создается, к сожалению, именно такими статьями (уже далеко не первой).
Имидж чей? Go? Пайка? По статье же видно уровень постановка задачи, уровень аргументации, результаты. Многое становится понятно из структуры статьи. Так что если тут кто и создает имидж, так это авторы статей себе. Ну и немножко комментаторы друг другу.
Go и его сообщества.
Много объяснений с конкретными примерами от авторов языка — github.com/golang/go/wiki/GoTalks
НЛО прилетело и опубликовало эту надпись здесь
Складывается впечатление, что Go создан был не чтобы на нём программировать, а чтобы его обсуждали :)

Кому и что пытаются доказать авторы как прошлой, так и этой статьи — непонятно. У каждого своё мнение, каждый выбирает сам. Обсуждать запятые в языке — сильно щепетильно для языка ПРОГРАММИРОВАНИЯ. А иначе это бессмысленный холивар, что мы собственно и там и тут и видим. Судя по всему, хабру нравится почесать языком и поспорить.

divan0, ты тут самый ярый Go любитель, любишь писать статьи, но они часто выходят очень субъективные (как и эта). Если уж хочется популизации golang, то пиши побольше практических статей, ведь решать практические задачи на go очень быстро и просто, а главное и по бенчмаркам получается красота.
Эта статья — исключительно контр-ответ на не совсем адекватный выпад, который, к сожалению, люди уже тиражируют и репостят, не читая. Вот вам реальный случай:
Пока читал вброс от Ильи хотелось дать ему леща отцовского, да обещал в интернетах не срываться. :) Для меня самые важные показались последние абзацы, потому что я уже потратил 6 мес на своей работе внедряя Go. (Пока результат не очень — пишем внедряем, выпиливаем потому что все боятся начинать). И что самое страшное после каждого выпиливания, я получаю набор статей от моих коллег типа той что состряпал Илья, как аргумент что язык сырой и что пока рано на него переходить. Я смело могу сказать что болтовня таких малолеток не только замедляет развитие языка, но еще и не дает развиваться специалистам, которые хотят его попробовать в продакшене. Но Илье то этого не понять, потому что сидя за партой в школе можно только догадываться о том как же живет программист в реальном мире и на сколько трудно привносить какие-то новые технологии в старые компании.
Ну, я могу предложить автору этого ответа использовать аргументацию «Go не сырой, он production ready, а статьи о его убогости как языка, это абсолютно ортогональная тема! Он должен быть таким by design, Великий Пайк так сказал».
Собственно то, чт овы процитировали — это не спор и даже не ответ и не аппеляция. Так спорят только мудаки, по двум причинам:
1) никаких фактов в целых 8 строчках текста
2) унижение оппонента по признаку возраста/пола/etc.

Ваша цитата — снова пустой спор и болтовня. Ваша статья — это «не совсем адекватный выпад» на «не совсем адекватный выпад». Проще говоря, у вас «бомбануло» и вы с радостью втянулись в холивар. А холивары — это бестолковое занятие.
Для вас ваш выпад может и кажется адекватным. Но вы субъективны :) Как пьяный за рулём, который утверждает, что водит даже лучше, чем когда он трезвый. Он сам в это свято верит.
Евнух, так можно про каждый комментарий писать. Это же не дискуссия уже. Вот ваш комментарий — тоже пустой спор и болтовня. и вы субъективны.

Какие факты? Человек, рассказавший, как ему неадекватные вбросы приводит к реальным проблемам на работе — должен анонимусам в интернете «факты» писать? Справки с работы и видеозаписи общения с боссом? О чем вы? :)
И «школьник» — это не унижение, автор статьи нам знаком и он, действительно, учится в школе.
потратил 6 мес на своей работе внедряя Go

Пока результат не очень

Сдаётся мне, там далеко не только из-за статьи школьника проблемы
Безусловно. Но, если вы когда-нибудь пробовали внедрять новые технологии в очень консервативную среду, то должны знать, что это процесс зачастую непростой и встречающий массу сопротивления.
А зачем заморачиваться? Если среда настолько инертна, лучше ее покинуть и найти место поприятнее, а среда пусть себе дальше потихоньку гниет.
Так и происходит обычно, но это всё процессы, занимающие месяцы/годы и отнимающие силы, ресурсы и эмоции.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Go это не Python, это разные языки. Некоторым людям сложно даётся факт, что никакие языки, кроме Питона, не являются Питоном

Go — это другой язык, это не C++.

Ничто не воробей, кроме воробья.

По теме — за Go наблюдаю и пишу для себя уже с пол года, но вот пока так и не решился перейти на него в компании из-за расходов на «адаптацию программиста» к новому яп и его «правилам», все же порог вхождения для программистов с не таким ветеранским стажем — это не две недели…
Хотя в общем-то очень хочется, но после php и python, Go ломает головы и как мне кажется — это и влечет за собой столь бурные холивары да статьи как прошлая и сегодняшняя. На самом деле язык хороший, но просто другой.
Да что в нем такого «другого»?
Добавьте в Pascal GC и concurrency на корутинах с каналами, замените nominal typing то ли на structural, то ли вообще на duck typing — вот вам и Go. В самом языке нет вообще ни одной новой или даже просто малораспространенной идеи.

Почему я должен считать этот язык чем-то необычным и мерить его какими-то другими рамками?
Ну а почему в нем должно быть что-то прям вот обязательно новое или малораспространенное?
Да, не будем спорить, в Go есть минусы, но благодаря сообществу — они почти все известны. В php вон вагон и маленькая тележка таких косяков, но тем не менее :) А возможно даже что-то исправится в перспективе. Вы конечно можете взять Pascal и поиграть в X-Zibit'a, но зачем? Go прекрасно решает свои задачи и на нем уже не один десяток проектов успешно работает. Например мы внедрили у себя InfluxDB и несмотря на то, что проект еще не в релизе, он вполне себя хорошо показывает.
Не, вы не поняли.
В Xzibit-а с паскалем уже поиграли создатели Go, а теперь его фанаты пытаются скормить нам точку зрения, что то, что нам неудобно — это такой особый go way, а не то, что язык by design сделан убогим и устаревшим.

Да, они решили некоторые актуальные проблемы в, скажем так, workflow, но не такой же ценой, что стоит задуматься о написании кода — начинает тошнить!
Ах вот оно что :)
Все же, что-то мне подсказывает, что тошнота от языка исключительно субъективное ощущение. Так вот могу сказать, что такие позывы вызывает ruby, но это же не делает его чем-то прям категорично плохим? Лично для меня, возможно в силу опыта, Go пока вызывает ощущение — «нет, я пока не готов», но опыт коллег по цеху говорит, что в целом вполне можно и не плохо получится на выходе.
Я-то давно готов, у меня ~5kloc Go в продакшне, я регулярно интересуюсь исходниками рантайма Go и вполне этот рантайм одобряю и вообще, считаю что подобный язык реально нужен — с GC, статическими бинарниками, правильно сделанным параллелизмом и concurrency. Идеи реально хорошие.

НО. Сам по себе язык Go, его подчеркнутая убогость, и подход его создателей «это сложно, поэтому нинужно», «вам не нужно этого знать» — реально вызывают неприязнь и нежелание с этим работать.
насчет ветерана спасибо льстит )

я долго присматривался на что поменять пхп
выбрал Го и пока не жалею

в адаптации для веб программирования на Го после пхп стоит понять несколько отличий
1
пхп рожден для того что, бы умирать
не помню кто сказал но это факт
исходя из этого у каждого запроса свой контекст исполнения заполняемый за нас пхп
в контекст входит $_POST, $_FILES, $_GET и т.д.

в Го для этого есть указатель на структуру *http.Request из которой можно получить большую часть информации о запросе
а так же интерфейс http.ResponseWriter куда нужно положить загаловки и ответ на запрос

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

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

а так лично для меня Го оказался не сложнее пхп в освоении
:) Со всем согласен, мы поняли это в момент перевода части проектов с пхп на питон. В общем-то питоном пока довольны как яп, но вот скоростью не очень, поэтому и смотрим в сторону Го, хотя с внедрением celery проект ожил и Го пока отложен в ящик.
А вы уверены, что у вас боттлнек именно в ЯП? Можно и на Go легко нагородить такого неповоротливого монстра (особенно, когда нет опыта разработки на нем), что по скорости выигрыш будет практически незаметен.
Собственно я не говорил, что узкое место — яп. Как раз наоборот, с пересмотром архитектуры большинство проблем решилось. Но даже сейчас есть моменты в которых, как мне кажется, компилируемый язык был бы лучшим решением, особенно с точки зрения деплоймента (специфично для проекта).
ПХП можно почти на что угодно менять и быть довольным :-D
критика «дизайна сокрытия переменных» должна подразумевать предложение альтернативного, более удачного дизайна — тогда дискуссия имеет шанс быть предметной.


Первый удачный дизайн:

var c = new Something();
{
  var c = new Something();
}

Результат:
CS0136	A local or parameter named 'c' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter


(Проще говоря, если поведение дает ошибки чаще, чем хотелось бы, уберите его. Я думал, в Go именно такая философия, разве нет?)

Второй удачный дизайн:
let Secret () = (42, 1)

let a = 0
a |> printfn "before %A"
begin
    let (a, _) = Secret()
    a |> printfn "inside %A"
end
a |> printfn "after %A" 

Результат:
before 0
inside 42
after 0


Но:
let Secret () = (42, 1)

let a = 0
a |> printfn "before %A"
let (a, _) = Secret()
a |> printfn "inside %A"
a |> printfn "after %A" 

Результат:
error FS0037: Duplicate definition of value 'a'


(Проще говоря, shadowing есть, а вот побочек нет)

Напомню поведение Go
	number := 0
	fmt.Println("before", number)
	{
		number, _ := Secret()
		fmt.Println("inside", number)
	}
	fmt.Println("after", number)

Результат:
before 0
inside 42
after 0


Теперь:
	number := 0
	fmt.Println("before", number)
	number, _ := Secret()
	fmt.Println("inside", number)
	fmt.Println("after", number)

Результат:
no new variables on left side of :=


Но:
	number := 0
	fmt.Println("before", number)
	number, err := Secret()
	if err != nil {
		panic(err)
	}
	fmt.Println("inside", number)
	fmt.Println("after", number)

Результат:
before 0
inside 42
after 42

вы опускаете специфику языка, такой reassing сделан прежде всего чтобы не делать err1 err2 и т.п., также стандартной проверкой является всё же
if number, err := Secret(); err != nil {
panic(err)
}
ну и больше фантазии нужно для имен переменных, это для любого языка справедливо
(Вы как-то себе противоречите. Больше фантазий нужно для имен переменных, но переназначение сделано, чтобы не плодить имена переменных.)

А если серьезно, то если «специфика языка» ведет к неожиданному поведение — может, все-таки, что-то с дизайном не так?
Не считаю эту статью убедительным опровержением изначального «наброса». Да, возможно эмоций и количества слова «шапито» в первой статье и перебор. Но вещи, на которые указывал автор, имеют место и отчасти (кроме очевидных ошибок с «забавным сокрытием переменных») они не приносят удовольствия.
Go красивый, быстрый язык и было бы хорошо, чтобы в нём было больше удобного синтаксического сахара и меньше странностей вроде кодогенерации. Я вот не считаю, что «все договорились что-то там писать в комментариях» должно влиять на поведение программ. Автодокументирование кода и помощь IDE — это отлично. А изменение логики через комментарии — это откровенно не лучшая идея.
Комментарии не меняют логики программ, автор вас ввел в заблуждение.

go generate используется для стандартизации рабочего процесса, позволяя любые кодогенераторы (для Protocol Buffers, Thrift или SWIG) вызывать одной командой — go generate, а не заставлять каждого писать мейкфайлы.
Возможно. Я до этой части go не добрался и не вправе судить. Хотя даже после такого объяснения у меня возникает вопрос — почему бы не использовать что-то вроде менеджера пакетов и чем же так плохи makefiles? Мне кажется, у go однажды эта концепция изменится. Но это не плохая сторона языка, а лишь особенность. Она писать код не мешает абсолютно.
А вот постоянная ругань компилятора на инклуд мешает и хочется иметь возможность отключить эту опцию на время отладки приложения. А когда собирать для production — тогда пожалуйста, пусть кричит на всё и вся.
Отказ от мейкфайлов — это желание упростить процесс сборки, убрать необходимость в ещё одном «языке», ещё одном слое потенциальных проблем, ошибок и сложности.
Все проекты в Go собираются командой «go build» или «go build ./..» (для рекурсивной сборки проектов в поддиректории). go generate появился в Go 1.4, как ответ на все чаще возникающие проекты, в которых нужно было запускать время от времени какие-то кодогенераторы — специально ради них городить подобие мейкфайлов было бы никудышним решением.

Не думаю, что авторы Go когда-либо допустят злоупотребления вот такими «специальными» комментариями — уж слишком долгие и широкие дискуссии вызывает каждый пропозал. «Просто так», «по неосмотрительности» в Go решения не попадают. Если появится надобность в новых «специальных комментариях», то будут искать более оптимальное решение. Пока же это один go generate — никаких проблем реально нет. Удобное решение для конкретной практической задачи.

Про инклуд уже писал выше. Да, сам сначала возмущался — ведь так непривычно. Сейчас не представляю, во чтобы превратился мой (и чужой) Go код, позволяй мне компилятор «иногда отключать» эту ошибку.
НЛО прилетело и опубликовало эту надпись здесь
Да, про CGO я забыл, так как уже почти не встречаю в реальности — но на заре Go это был очень полезный инструмент, который использовался, разумеется, не так, как в вашем примере.
НЛО прилетело и опубликовало эту надпись здесь
Потому что потребность в работе с сишным кодом уменьшается с каждым месяцем, хотя и так была невелика.

Да, могут, но только если вы специально захотите это сделать, и разберетесь в том, как и зачем это делать. Реальность Go такова, что когда речь заходит о таких специфических случаях, это оказывается банально простой и удобный способ. Со стороны, конечно, это не очевидно.
Про слайсы и индексы очень много букв, но всё совершенно неубедительно.
Считаю недоумение автора предыдущей статьи справедливым.
Очень бы хотелось увидеть сравнение Go с Nim. Смотрел на Go, но так им и не проникся. Nim выглядит куда более обещающим.
Опоздал я к пьянке, но напомню, что два года назад постил «Воображение, как у Эсмеральды», а там был такой абзац:
Go — это язык для программирования на Go, а не новый синтаксис для Java, для Haskell, или для других существующих языков. Чтобы написать хорошую программу на Go, нужно мыслить по-другому, чем при программировании на Java. Вместо этого современные программисты сокращают путь: берут готовый код, и переписывают его на Go. Код на Go при этом, действительно, порой выходит неуклюжим. Но дело не в Go: если бы эту же программу с самого начала писали на Go, используя другие подходы — более естественные для Go и менее применимые в той же Java — то код бы получался более живой и яркий. Но чтобы научиться мыслить по-другому, нужно затратить время и силы — больше, чем критики Go могут себе позволить. Насколько проницательных отзывов о Go вы могли бы ожидать от человека с десятью годами опыта на Java и десятью минутами опыта на Go?

Вместо Java можно подставить С++, Python или любой другой язык, и этот абзац останется верным.
Вместо Go тоже можно подставить любой язык и выражение останется в той или иной степени верным (в зависимости от близости итоговой пары языков).
Да, но другие языки реже подвергаются критике типа «А чего тут всё не как я привык?»
Питон — а почему отступы значимые?
С++ — а почему такая долгая компиляция? Почему такие сложные шаблоны?
Rust — почему неудобный синтаксис? Почему медленнее С++?
Php — ну на эту тему сотни статей есть
и т. д.
Всё так, но, смею полагать, это больше не о бекграунде, а о личностных характеристиках. У нас недавно был выпуск подкаста о Go с джавистами, очень здорово пообщались. И вот, джавист со стажем рассказывает о Go, очень неплохо получилось имхо :)
Рассказывает весело, но сколько же там неточностей и фактических ошибок… Боюсь, слушатели скорее запутались:)
Кстати, спасибо за перевод. Не видел этой статьи раньше, отлично и ёмко написано, в тему.
Называть это «плохим дизайном языка» — чрезвычайно глупо

Дайте ваше определение "плохого дизайна языка".


Помимо этого, каждый импорт — это замедление процесса компиляции, и там где Go-программисты не успевают моргать глазом, С++-программисты идут пить кофе и ждать

С(++) — чуть ли не единственные языки, которые замедляются неиспользуемыми инклудами. Все остальные как-то не замедляются.

Вот вам делать нечего некропостить.

А что до замедления, если верить этому stackoverflow.com/questions/14038691/does-unused-imports-in-python-hamper-performance, то Python тот же таки замедляется. И это логично, это же не комментарии, чтобы вообще ничего не затрагивать. В C# рантайм время не пострадает, а вот компиляция, отладка, подсветка синтаксиса и прочие фичи IDE — запросто. По сути, все языки этому будут подвержены в той или иной степени. И никуда от этого не денешься.

Публикации

Изменить настройки темы

Истории