Блог компании Mail.Ru Group
Go
Анализ и проектирование систем
Параллельное программирование
Программирование
Комментарии 189
-5
Люди зачем-то пытаются писать вне Гугла на языке, который Гугл придумал исключительно сам для себя. И удивляются, что получается плохо.
-5
Ангулар был создан гуглом для гугла. Как по мне, когда он вышел, избавил многих от головной боли в написании одностраничных приложений и получалось хорошо.
А Го хорош там, для чего он создавался. А те, кто его пытаются засунуть туда, где ему не место — потом хейтят.
0
Тут сидят молодые разработчики на Реакте, которым сказали на гурсах гикбрейнса, что Реакт — совершенство, а Ангулар — зло. Теперь они ходят по комментариям и минусуют все записи, где фигурирует Ангулар. Ну-ка товарищи, которые минусуют, скажите альтернативу первому Ангулар, когда он только вышел?
-2
Потому что неплохо так получается. Да и разве в языке дело, а не в инженерных задачах и подходах к их решению?
+1
Неплохо так получается в случаях, когда Ваши задачи и подходы в их решении случайно совпадают с гугловскими. Это делает Go похожим на какую-то библиотеку, а не на язык программирования общего назначения.
0
Написано: сервис массового импорта товаров, обработки изображений под highload, мобильный back для мессенджера, протокол обмена сообщениями в Ethereum, куски самого Ethereum, всякие мониторинги до кучи.
Где что-то из этого совпадает с Гуглом, кроме мониторингов?
0
Думаете у гугла нет сервисов массового импорта, обработки изображений или бекендов мессенджеров? Именно для такого го и делался. Мне вот было бы интересно посмотреть на его применение в чём-то десктопном (с UI), в системном программировании, в мобильной разработке. Но таких кейсов нет, всё сводится к «принять 2 байта по сети, отправить 2 байта по сети».
-3
Повторюсь, ну вот я сейчас в мобильной разработке пишу back. То есть гошка крутится к клиента на телефоне и подключается к фронту.
+1
не для создания API <...>, а для реализации бизнес-логики

странное противопоставление: API же не существует само по себе
+1
Не совсем. Есть узкий спектр задач, когда необходимо реализовать внешнее API как обертку над существующим сервисом. С развязкой через tcp/rest/etc. При этом логики в таких обвязках довольно таки мало. Конвертация параметров, конвертация представления данных в запросе, etc.
0
> Главное отличие в том, что var позволяет объявлять без инициализации (потом приходится объявлять тип)
Можно пример без инициализации? Т.к. инициализая все равно происходит.
Считаю, что отличие в «non-declaration statement outside function body».
Нельзя написать a := «test» вне функции.
+1

Всё несколько глубже. Вот более-менее полный список нюансов про := и var.


Факты:


  • явно указать тип можно только в var
  • наглядно сгруппировать (в скобках, с выравниванием) несколько переменных можно только в var
  • создать глобальные переменные может только var
  • создать переменные локальные для if, for, switch может только :=
  • задать смесь новых и существующих можно только в :=
    • использование := в этом случае избавляет от лишних строк объявляющих
      переменные да ещё и с обязательным указанием типа (что не всегда
      возможно — в переменной может хранится значение не экспортируемого
      типа возвращаемое некоторыми конструкторами)

Выводы:


  • var более функционален для объявления новых переменных
  • var более нагляден для объявления новых переменных
  • var защитит от случайного изменения существующих переменных вместо объявления новых (go vet -shadow, go-nyet и т.п. могут детектить shadowing, что может снять претензию к := — а плюс в том, что не нужно заранее объявлять и указывать тип)

И пара цитат из книжки Кернигана:


  • var name type или var := value в зависимости от важности инициализации начальным значением.
  • if err := ...; err != nil {} для уменьшения области видимости err.
+6
странно, когда в языке, вроде как с строгой типизацией, дают возможность делать много неявных вещей…

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

добавили бы уже опцию компилятора\макрос к функции: если string пытаешься свести к int и panic — возвращать 0, один фиг явность в go условная…

+1

не сильно понял пример, в чем проблема там? Интерфейсная переменная содержит тип и указатель на значение. Конечно же когда пытаетесь сделать type assertion интерфейсной переменной в другой тип, а не в тот тип, который переменная содержит, получаете панику.

-1
Да давно уже понятно, что Go это тупо хайп, который уже сейчас начал спадать. Практически все кто писал на серьезных языках типа С#/Java от Go просто чертыхаются. Ибо он реально ущербный какой-то.
-1
Ну я, например, долгое вермя писал(и пишу) на C#/Java и мне Go нравится.
-1
Спасибо, качественная статья, по совокупности пока не вижу ничего лучше Go а различные подводные камни можно тем или иным образом обходить.
0

Имейте уважение к автору, который утверждает обратное:


До недавнего времени у нас не было реальных альтернатив там, где царит Go: в сфере разработки эффективных, нативных исполняемых файлов без мучений C или C++. Rust быстро развивается, и чем больше я с ним работаю, тем больше он мне кажется крайне интересным и тщательно продуманным. Я считаю, что Rust — один из тех друзей, с которыми сначала не так просто поладить, но потом хочется долго с ним общаться.
-1
Прямо видно как комьюнити сильно разделилось на тех кто пишет на Go, но жалуется на его недостатки и тех кто хвалит Rust за его эффективность, но фактически язык не востребован на рынке. С моей точки зрения Rust конечно эффективнее и лучше задуман, но читать код на нем мне просто больно. И это как борьба асемблера с Си, Си менее эффективен, но он удобнее. п.с. может Go 2.0 спасет нас всех? ))
+1
Они получили высокую производительность и небольшое потребление ресурсов памяти/процессора/диска.


Прекрасная статья. Go решает на мой взгляд очень узкую проблему как метко заметил автор статьи. У меня была задача запустить тысячу нодов кластер и опа-на! я обнаружил, что тот же ТомКет просит под сервер с апп 380М памяти, а Го скромно укладывается и на 60М. Пришлось ударными темпами переписывать под Го.

+2
В Rust такая же проблема: поскольку в нём нет исключений (действительно нет, в отличие от Go)

Но ведь в Rust есть точно такой же panic и его так же можно поймать и отменить…
0

Подскажи как отменить панику, если в настройках стоит panic = abort?

+3
Никак, но это и не поведение по-умолчанию.
Я-то в курсе, что panic в rust это совсем не то, чем кажется, просто в статье слишком безаппеляционно сказано, что исключения в Go есть, а в Rust нет.
+8
Автор так старался поддерживаться нейтралитета, что записал два недостатка в преимущества.

Прекрасная стандартная библиотека
Это скорее в недостатки. Библиотека как для нового языка — непоследовательная и непродуманная. Чего только стоит совершенно разные подходы к парсингу в flag (через ссылочную муть с тонной копипасты и никакой декларативностью) и json/xml (через теги). При это flag — совершенно не критична к производительности, ведь парсинг запускается лишь однажды!

Стандартизированный тестовый фреймворк
А это в «Ужасный». Серьезно, фреймворк настолько отвратительный, что лучше его бы не было. В нем просто никаких преимуществ, даже банального Assert нету, а из-за отсутствия Generic написать свой, адекватный — крайне сложно. То есть банальный Assert из C# в Go выглядит так (в синтаксисе мог ошибиться, т.к. давно не писал):
a := fn()
if a != 10 {
  t.Fail(fmt.Sprintf("Expect a to be (%v), actual: (%v)", 10, a);
}


-4

Библиотека в целом отличная. Да, там есть проблемы, как упомянутые Вами так и другие, и да, если бы вся библиотека была написана исключительно гениями из альфа-центавра, не допустившими ни одной ошибки проектирования в её коде — было бы лучше. К несчастью для нас — её писали люди. Тем не менее, в среднем код стандартной библиотеки заметно лучше среднего, намного лучше поддерживается (исключая не очень удачные пакеты, от которых решили отказаться — вроде net/rpc), и очень помогает то, что весь этот функционал в принципе есть из коробки.


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


Тестовый фреймворк отличный. И свою задачу он выполнил — отсутствие assert-ов стимулировало попробовать писать тесты в табличном стиле, и помогло оценить этот подход. А потом assert-ы элементарно добавляются поверх, например: https://godoc.org/github.com/powerman/check

+4
К несчастью для нас — её писали люди
Можете привести похожие примеры в стандартной библиотеке, к примеру, C#?

тесты в табличном стиле
Которые, кстати, тоже вручную пишутся. Класс. Так зачем такая надобиблиотека? И вы называете её классной просто потому что из-за неудобства вам приходится искать способ занять позу поудобнее? Очень похоже на Стокгольмский Синдром: «насильник был хороший, потому что я сам мог выбрать позу»
0
Плюс help для каждого флага занимает много места, и внутри тегов это бы смотрелось не очень
Ну а это вы уже совершенно уродский дизайн тегов в языке осуждаете. Какой наркоман до такого додумался — я не знаю. Во всех адекватных языках аналоги позволяют писать текст любой длины в анотациях без всяких проблем:
[ObsoleteAttribute("This property is obsolete. Use NewProperty instead.", false)]
public static string OldProperty

Я просто уже не стал добавлять в Ugly от себя и только прокоментировал неудачные «плюсы» из топика
+5
Вот зря вы так про стандартную библиотеку. Она очень мощная.

Сравниим, к примеру, банальную сортировку.
Для Python всего то есть sorted, да у списков метод list.sort имеется. Весьма и весьма куцо. А вот у Go есть целый отдельный модуль sort. Тут и сортировка строк, и сортировка целых, и сортировка флоатов!

Или, например, в Go есть полезнейший пакет errors с инструментами для упрощения работы с ошибками. Он даже в отдельной директории находится, настолько он важен. В Python банально нету аналога для такого модуля.
+8
А вот у Go есть целый отдельный модуль sort. Тут и сортировка строк, и сортировка целых, и сортировка флоатов!

Я же правильно понял, что это такая издевательская ирония?

+4
Т.е. «не имеющий аналогов» «полезнейший пакет errors» не смутило? :)
+7
Кстати, «из коробки» начиная с 1.8 можно ведь сортировать и slice-ы! А чтобы это было быстро (рефлексия ведь), добавили специальную функцию reflect.Swapper. Так что библиотека не только мощная, но еще и гибкая!
0
Простите, но:
func Assert(cond_ bool, str_ *string){
    if !cond{
        panic(fmt.Sprintf("ERROR: ", str_))
    }
}

Вставляете в любое нужно место в качестве пре-, ин- и пост условия (а можно и просто panic), а если ещё внимательно почитаете про recover и гарантированный defer — жизнь станет на много легче.
Также вы, похоже, всё же не понимаете методику проведения проверок на допустимость значений в golang и как обрабатывать ошибки.

Да и обработка ошибок делается не так:

if a, err := f(); !err{
    ...bla-bla-bla...
}
 if a==0{
        ...bla-bla-bla..
 }else{
        ...bla-bla-bla...
    }
}
0
Всякие Assert нужны вовсе не для того, чтобы тупо кинуть панику, а чтобы напечатать детальное сообщение при фейле теста (мол ожидали то и то, получили это). И не просто fmt.Sprintf("expected %v, actual %v", expected, actual), а удобочинаемый дифф, чтобы потом не ломать себе глаза, высматривая «ну и где же тут, !»№%, отличие...". Хорошие сообщения о фейлах очень и очень помогают при анализе ошибок на всяких CI.

Для сравнения посмотрите (я даже не прошу внимательно читать, просто глянуть одним глазком), как это сделали, например, в Python.
type-specific equality function will be called in order to generate a more useful default error message
А если у вас свои структуры данных, то в фреймворк можно добавить хук для своего типа.

если ещё внимательно почитаете про recover и гарантированный defer…
Также вы, похоже, всё же не понимаете методику проведения проверок на допустимость значений в golang и как обрабатывать ошибки.
Ну может быть вы нас просветите. А то мы люди темные, читали невнимательно.
0
Вы так написали, как-будто всю эту информацию нельзя сделать в голанге?)))
Хотите своих хуков? Ну напишите декоратор, никто вам не мешает. Не нравится декоратор — реализуйте интерфейс, что в используется в структуре данных. Это всё делается и вполне доступно описано.

Откройте книжку Роба Пайка, и посмотрите пример по выводу тайминга работы функции, реализованную через defer _внезапно_ с отложенной анонимной функцией (ленивые вычисления, привет Скале). И десятом строк ниже, как пробрасывать тип error сквозь любое количество уровней с навешиванием информации на каждом уровне.
Например, стр. 180, 186-187 (полный и подробный вывод стека), стр. 187 и дальше — отличное описание recover. Если это всё вы внимательно читали, то должны были усвоить в том числе — почему в golang нет try/except/finnaly.
0
Вы так написали, как-будто всю эту информацию нельзя сделать в голанге?)))
Ну так мы то говорим в контектсе «богатство стандатной библиотеки». Из коробки таких функций нету (вообще почти ничего нету).

Откройте книжку Роба Пайка, и посмотрите пример по выводу тайминга работы функции, реализованную через defer _внезапно_ с отложенной анонимной функцией (ленивые вычисления, привет Скале). И десятом строк ниже, как пробрасывать тип error сквозь любое количество уровней с навешиванием информации на каждом уровне.
Не могли бы вы снабдить ссылкими? Или цитатами. А то, знаете ли, в 21 веке я меньше всего хочу вручную отсчитывать номера страниц и строк.

Если это всё вы внимательно читали, то должны были усвоить в том числе — почему в golang нет try/except/finnaly.
Моя ваша не понимать. Речь была про «testing» и его убогость, а вы переводите в сторону холивара «экепшны в Go»… Тема, безусловно, интересная, но ее обсуждение совершенно бесперспективно.

А про все эти трюки с навешиванием инфы через defer, пробросы ошибок через панику, оборачивания, дофичагачивание стектрейса (зачастую сделанного в месте логирования ошибки, а не ее генерации, лол) и прочее я в курсах… Правда, как показывает практика, зачастую обработка ошибок в Go выглядит так:
if err != nil {
	return nil, fmt.Errorf("some error: %v", err)
}


PS: "(ленивые вычисления, привет Скале)" — вы это так написали, будто бы это единственный известный вам язык, где есть ленивые вычисления…
-1
Ну так мы то говорим в контектсе «богатство стандатной библиотеки». Из коробки таких функций нету (вообще почти ничего нету).

Богатство?
1. Я где-то употребил это слово?
2. Мы говорим про то, что это вполне реализуемо, вообще без напряга, если это вам действительно надо.
Не могли бы вы снабдить ссылкими? Или цитатами. А то, знаете ли, в 21 веке я меньше всего хочу вручную отсчитывать номера страниц и строк.

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

Моя ваша не понимать. Речь была про «testing» и его убогость, а вы переводите в сторону холивара «экепшны в Go»… Тема, безусловно, интересная, но ее обсуждение совершенно бесперспективно.

Думаю, Вы искренне не понимаете. Речь шла не про testing. Речь шла про отладку и посмертный дамп. И как раз в этой теме golang сделан несколько разумней чем try/except/finnaly чем в python. Хотя, лично моё мнение — golang не особенно далеко ушёл вперёд. Ещё раз: речь не про try\execpt\finally. Речь про отладку.

(зачастую сделанного в месте логирования ошибки, а не ее генерации, лол

Ну, не все руки одинаково прямые. Тут от языка не зависит.
Правда, как показывает практика, зачастую обработка ошибок в Go выглядит так:

Ну, частенько так и есть, и это в рамках логики обработки ошибок. (всё те же страницы, что я вам привёл).
PS: "(ленивые вычисления, привет Скале)" — вы это так написали, будто бы это единственный известный вам язык, где есть ленивые вычисления…

Я так написал, потому что именно Скала наиболее часто упоминается как язык с функциями не имеющими побочных эффектов, что позволяет ленивые вычисления и жестокую параллельность.
+3
Изначально вы отвечали на коммент TheShock, где он писал дескать «это ложь, что библиотека в Go хорошая; например вот модуль testing просто ужасен».

Речь шла не про testing. Речь шла про отладку и посмертный дамп.
Как раз про testing речь и шла. Перечитайте внимательнее.

Я так написал, потому что именно Скала наиболее часто упоминается как язык с функциями не имеющими побочных эффектов, что позволяет ленивые вычисления и жестокую параллельность.
Вы, наверное, живете в параллельной вселенной. Ну или поисковики вам выдают статьи по скале, подстраиваясь под ваши интересы. А вообще, например, в статье на вики Scala даже не упоминается, зато есть и Haskell, и OCaml, и Scheme…
0
Речь шла не про testing

Прочитайте внимательно мое сообщение, я процитировал статью. Речь была о «Стандартизированный тестовый фреймворк»
+2
Если это всё вы внимательно читали, то должны были усвоить в том числе — почему в golang нет try/except/finnaly.

try/except/finally — это действительно плохо. Но плохо оно тогда, когда в вашем языке есть альтернатива в виде монадической обработки ошибок, и это не случай Go.

реализованную через defer _внезапно_ с отложенной анонимной функцией (ленивые вычисления, привет Скале)

А можно для незнающих Go настолько детально, чем это аналогично ленивым вычислениям?
0
try/except/finally — это действительно плохо. Но плохо оно тогда, когда в вашем языке есть альтернатива в виде монадической обработки ошибок, и это не случай Go.

Вне всяких сомнений Go, как достаточный и непротиворечивый язык сделан… так себе. Этот язык такой же мой, как и ваш. Но как по мне — он безопаснее питона.

А можно для незнающих Go настолько детально, чем это аналогично ленивым вычислениям?

Я сам сильно не знаю. Если я правильно понимаю:
значение переменных-функций вычисляется тогда, когда к им происходит обращение. Т.е. не было обращения — не за чем считать.
С помощью уже достаточно пропиаренной команды go — переменная функция может запустить анонимную функцию внутри себя с параллельным исполнением. Как приятный бонус — вложенная функция имеет доступ к обрамляющему пространству имён, и таким образом происходит реализация аналога статических переменных в функциях. Немного внезапно, но работает)
0
Этот язык такой же мой, как и ваш. Но как по мне — он безопаснее питона.

Питон — так себе образец для подражания с точки зрения типобезопасности.

С помощью уже достаточно пропиаренной команды go — переменная функция может запустить анонимную функцию внутри себя с параллельным исполнением.

Но ведь она выполняется всегда, разве нет? То есть, это не ленивые вычисления, а всего лишь параллельные.
-1
Питон — так себе образец для подражания с точки зрения типобезопасности.

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

Если вызывать напрямую — то это произойдёт сразу. Если вызывать, как анонимную функцию внутри переменной-функции — тогда вовсе нет.
0
И если принять за отправную точку, что голанг — замена питону, имхо — прогресс на лицо.

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

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

Если вызывать, как анонимную функцию внутри переменной-функции — тогда вовсе нет.

В смысле, она не вызовется, что ли?
0
Прогресс на самом деле тоже так себе, ...

Вы мне не покажете, в каком месте я написал «вот это прогресс!»?))

… и Go пользуется нулём из тамошних достижений.

А вы не подскажете, сколько среди программистов высоколобых математиков? Особенно, когда сделать надо было «ещё вчера»? И что же это высоколобые математики до сих пор не сделали идеальный язык программирования ещё 30 лет назад?))

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

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

В смысле, она не вызовется, что ли?

В смысле, при получении ссылки на анонимную функцию внутри вызываемой функции — нет, в тот момент не вызывается.
0
Вы мне не покажете, в каком месте я написал «вот это прогресс!»?))

После того, как вы покажете, в каком месте я написал, что вы написали, что вот это прогресс.

Если серьёзно, «прогресс налицо» предполагает некоторую степень новизны. Можно, конечно, действительно ограничиться [статической] типобезопасностью одного лишь питона, но зачем? Ассемблер возьмите, ещё эффектнее будет.

А вы не подскажете, сколько среди программистов высоколобых математиков? Особенно, когда сделать надо было «ещё вчера»?

А это совсем другой вопрос.

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

И что же это высоколобые математики до сих пор не сделали идеальный язык программирования ещё 30 лет назад?))

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

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

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

В смысле, при получении ссылки на анонимную функцию внутри вызываемой функции — нет, в тот момент не вызывается.

А когда вызовется-то?
-1
Можно, конечно, действительно ограничиться [статической] типобезопасностью одного лишь питона, но зачем? Ассемблер возьмите, ещё эффектнее будет.

А в ассемблере есть типизация из коробки? Управление памятью? Контроль границ массива? Ээээ… Вы зачем это написали?

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

Правда? Я правильно понимаю, что в голанге типизацию пользовать не принято?))

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

Не дай Бог, конечно. Но, знаете, дерьмо случается.
Это возможно с каждым.

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

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

А когда вызовется-то?

В момент обращения к переменной-функции, полученной по ссылке при обращении к функции (которая обрамляет и возвращает ссылку на анонимную функцию)
0
А в ассемблере есть типизация из коробки?

Статической примерно столько же, сколько в питоне (до тайпхинтов, по крайней мере).

Я правильно понимаю, что в голанге типизацию пользовать не принято?))

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

Правда, я ещё и не понимаю, какое отношение Go имеет к формальной теории типов, ну да ладно.

Не дай Бог, конечно. Но, знаете, дерьмо случается. Это возможно с каждым.

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

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

Я не думаю, что он существует, более того.

Однако, это не повод не сравнивать и не оценивать имеющися языки.

В момент обращения к переменной-функции, полученной по ссылке при обращении к функции (которая обрамляет и возвращает ссылку на анонимную функцию)

Я могу из неё вытащить результат и передать в какую-нибудь другую функцию, но чтобы этот результат вычислился только тогда, когда эта самая другая функция этого потребует? Нужно ли мне писать эту другую функцию каким-то особым образом для этого?
+3
Простите, но:
func Assert(cond_ bool, str_ *string){
    if !cond{
        panic(fmt.Sprintf("ERROR: ", str_))
    }
}

То есть стандартная библиотека Гоу настолько отвратительная, что даже такая функция ее украсит?
Кстати, функцию вы написали тоже отвратительную, но, видимо, евангелисты Гоу даже такое говно приводят в пример. В C# ценность AssertEquals в тестах в том, что я могу посмотреть, какое значение получилось, а не просто «получилось неправильное значение». А еще у вас на какую строку укажет эта ошибка? Там где случилась ошибка, или на библиотечную? И как на счет того, чтобы выполнить все тесты, а не упасть только на первом?

Или я не понял — это был очередной сарказм, где в виде положительного отзыва вы приводите негативный пример языка, как anjensan?
-2
Простите, но
1. Я не считаю эту функцию отвратительной и пример прекрасной функции вы не удосужились привести. Считаем, предмет обсуждения исчерпан. Ну вкус и цвет все фломастеры квадратные. Если вам в консоли нужны цвета и бики — ну так не поленитесь: либо сами напишите, либо возьмите готовое. Стандартная библиотека в Го достаточная чтобы в пять строк поднять сервер и ещё в десять навесить пару обработчиков с шифрованием и параллельной обработкой.
2. Вы меня с кем-то путаете. Я никоим образом не отношусь ни к евангелистам Го, ни вообще к профессиональным программистам. Чукча не писатель, чукча читатель. Если у чукчи дети в холодильнике греются — ему всё-равно какой формы холодильник. Если уж на то дело пошло, я предпочитаю Паскали и Обероны.
3. Вам никто не запрещает посмотреть что получилось. Делается дописыванием параметров.
4. Вы можете не падать в ассерте, а только вывести лог. Я думал, вы знаете, что есть хард ассерт(интересный паник), и софт ассерт (красная лампочка для ленивых).
5. Это не был сарказм, это исключительно ваше желание увидеть то, что вы хотите увидеть. А не решить проблему.
+1
пример прекрасной функции вы не удосужились привести
Я же привел. Читаете через слово? Или вообще половину не читаете.

Ну вкус и цвет все фломастеры квадратные
При чем тут на вкус и цвет? Я описал, чем именно она плоха.

ну так не поленитесь: либо сами напишите, либо возьмите готовое
Сперва добейся? Но зачем мне это? В мире есть множество не таких отвратительных языков, как Гоу, языков с отличной стандартной библиотекой, в том числе библиотекой тестирования. Они уже добились и убрали в этом необходимость для меня.
-1
Хорошо, хорошо. Я не читаю, «сперва добейся» на собеседованиях не спрашивают, и вам это не надо. Названий хороших языков, впрочем я так и не вижу.
Ну, так если всё хорошо, что вы делаете в этой ветке?))
+4

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


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

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

И всё-таки вынужден повторить свой вопрос:
Ну, так если всё хорошо, что вы делаете в этой ветке?))

Я так полагаю, что обсуждение всегда начинается, чтобы найти решение проблемы (если она есть), а не заявить «язык гавно, потому что я хоть библиотеку не смотрел, ничего не искал, но вот в том языке, которому уже 35 лет (с использованием библиотек языка, которому уже 46 лет) в стандартной библиотеке это есть!»
0
Вы правда считаете, что вариант, который я предложил за 10 секунд — это итоговое решение?

Не знаю. Обсуждаем то, что вы представили.


Или если в стандартную библиотеку не входит какая-то плюшечка, которую вы так любите (при этом задать вопрос Яндексу лень) — это сразу плохой язык?))

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


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

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


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

0
Не знаю. Обсуждаем то, что вы представили.

Понятно. Не знаю, но обсуждаем.

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

Ещё раз повторю свой вопрос:
Ну, так если всё хорошо, что вы делаете в этой ветке?))

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

Итак, делаем поиск по статье и всему обсуждению с шаблоном «превосх». Есть вот это:
Стандартная библиотека Go действительно великолепна, особенно применительно к разработке сетевых протоколов или API: в ней есть HTTP-клиент и сервер, шифрование, форматы архивирования, сжатие, отправка писем и так далее. Есть даже парсер HTML и довольно мощный движок шаблонов, что позволяет создавать текст и HTML с автоматическим экранированием (automatic escaping) для защиты от XSS (к примеру, используется в Hugo).

В контексте написанного явно следует «хорошая библиотека», а не «библиотека на все случаю жизни». Думаю, тут может надо задать вопросы переводчику? Great — прекрасный, красивый, сильный. Но не как rich — богатый или big — большой.
0
Понятно. Не знаю, но обсуждаем.

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


Ну, так если всё хорошо, что вы делаете в этой ветке? ))

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


Вы там что, курите? В каком месте было написано «превосходная библиотека» в статье?

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

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

Т.е. то, что с самого начала условия, что должен делать код описаны не были (потом, задним числом было «а посмотрите вот тут»).
Как вопрос был задан — так я и ответил. Что-то ещё хотите? Ну так опишите, что вам надо.
Ну вообще я хотел сказать вам, что вы игнорируете что вам пишет TheShock.

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

Это меняет. Фраза безотносительно к языку «вот этого нет в библиотеке, поэтому язык — гавно» — это то, из-за чего программисту, претендующему на трудоустройство в мою контору — я, как директор и владелец, сразу говорю «спасибо, до свидания».
+2
Почему я должен брать в расчёт то, что мне не интересно или ошибочно сформулировано изначально?

Потому, что вы участвуете в диалоге, и, если вас не интересует, что говорит собеседник — что вы вообще делаете в этой ветке? :)

-2
Потому, что вы участвуете в диалоге, и, если вас не интересует, что говорит собеседник — что вы вообще делаете в этой ветке? :)

Объясняю. Я — говорю про go. Говорю про его косяки и сильные стороны. Товарищ ввалился со скудной аргументацией из области C# и на том основании, что go — не C#, делает выводы которые я должен принять к сведению. При этом, он больше не появляется, и если я даже лично сделаю ему хорошо — он этим пользоваться не будет. Зачем он написал то, что написал?
0
Зачем он написал то, что написал?

В статье была ложь о, цитирую: «Go поставляется с прекрасным тестовым фреймворком в стандартной библиотеке». Мне не нравится маркетологическая лодь, потому я ее опроверг, в т.ч. на примере.
0
потому что я хоть библиотеку не смотрел, ничего не искал
Почему не смотрел? Я вполне себе писал на Go, так что имею мнение прям с передовой, в отличии от вас:
1. Я не гофер. И даже не программист.

Тестовая либа в языке — отвратительная, приходится искать сторонние решения. Процитирую вам статью, которую вы, видимо, читали через строчку, раз пропустили эту фразу:
Go поставляется с прекрасным тестовым фреймворком в стандартной библиотеке
Я спорил именно с этим утверждением. Тестовая либа/фреймворк в Гоу — отвратительная, а автор утверждает, что она прекрасная. Нету в ней ничего прекрасного, приходится пользоваться или сторонними решениями, или писать глючные костыли типа вашего.
+2
Простите, но:
func Assert(cond_ bool, str_ *string){
    if !cond{
        panic(fmt.Sprintf("ERROR: ", str_))
    }
}
1. Я не считаю эту функцию отвратительной и пример прекрасной функции вы не удосужились привести.
Ну это уже на цирк какой то смахивает. Вот вам по пунктикам, в порядке моего офигевания:
1. code-style — что за 'cond_', зачем 'str_'; не надо так;
2. code formatting — куда делись пробелы между ) и {; go fix такой код не пропустит;
3. а нафига, простите, тут '*string', вместо 'string'; вопрос риторический, можете не отвечать…
4. придирочка — гораздо лучше сделать 'Assert(cond bool, fmt strging, a ...interface{}) (надеюсь не надо пояснять зачем); но я допуская что вы, как истинный сусликгофер, хотите сделать две функции Assert и Assertf, допустим;
5. в коде тупейшая ошибка! вместо «ERROR: » нужно писать «ERROR: %s».

Как по мне, так это вполне себе «отвратительный код».
-2
1. code-style — что за 'cond_', зачем 'str_'; не надо так;

Я вас не заставляю пользоваться таким оформлением. Не нравится — сделайте себе как нравится. Мне вот так удобно. На вкус и цвет — все фломастеры квадратные.
code formatting — куда делись пробелы между ) и {; go fix такой код не пропустит;

При сохранении или компиляции все пробелы будут вставлены. Это правда проблема?
3. а нафига, простите, тут '*string', вместо 'string'; вопрос риторический, можете не отвечать…

Не отвечаю. Таки зачем ви спрашивали?
4. придирочка — гораздо лучше сделать 'Assert(cond bool, fmt strging, a ...interface{}) (надеюсь не надо пояснять зачем); но я допуская что вы, как истинный сусликгофер, хотите сделать две функции Assert и Assertf, допустим;

1. Я не гофер. И даже не программист.
2. Хотите сделать универсальную функцию — сделайте. Я слабал пример за 10 сек, по поставленным условиям (которые вы теперь дописываете задним числом). Что не так?
5. в коде тупейшая ошибка! вместо «ERROR: » нужно писать «ERROR: %s».

Вот видите, какой вы молодец?! Вы же всё знаете, всё умеете. Ну так и напишите себе функцию без лишних слов.

В чём проблема то? Я так и не понял))
0
В чём проблема то? Я так и не понял))
1. Я не гофер. И даже не программист.
При этом активно спорите, что-то доказываете (частенько дичь всякую).
В этом, собственно, и проблема :)
-2
Вы задали вопрос. Я на него ответил: можно, например, сделать вот так.
Я не спорю, и не доказываю. Мне вообще наплевать на golang.
Я показываю возможный путь решения — с вашей точки зрения — проблемы, с моей точки зрения — задачи.
Возможно решение задачи показал? Показал.
В чём проблема?
0
в коде тупейшая ошибка! вместо «ERROR: » нужно писать «ERROR: %s».

И компилятор за это по рукам не даст? А что случится, рантайм-ошибка, креш или что-то ещё?

Круто, уже даже сишные компиляторы несколько лет как умеют на это ругаться.
+1
И компилятор за это по рукам не даст? А что случится, рантайм-ошибка, креш или что-то ещё?

Не даст, будет очень странная строка. Вот плейграунд:
fmt.Println("Hello, playground") // Hello, playground
	
str_ := "123";
fmt.Println(fmt.Sprintf("ERROR: ", str_)); // ERROR: %!(EXTRA string=123)
fmt.Println(fmt.Sprintf("ERROR: %s", str_)); // ERROR: 123
	
result := fmt.Sprintf("ERROR: ", str_)
fmt.Println(result) // ERROR: %!(EXTRA string=123)
fmt.Println(len(result)) // 27


На всякий случай я показал, что это действительно формируется такая строка, а не просто ошибка в консоль пишется и как результат — может улететь в базу в виде запроса или еще что.
+1
Ну, то есть, стек не портится, буферы не переполняются. И то хорошо.
+1
3. Вам никто не запрещает посмотреть что получилось. Делается дописыванием параметров.

Кстати, это интересно было бы посмотреть. Можно пример?
0
Здесь применяется мантра «Не взаимодействую с помощью общей памяти, делай память общей с помощью взаимодействия».

Этот принцип не подходит для одной из самой важной части бэкенда — базы данных или разного рода кешей. Когда есть большая структура-граф объектов в оперативной памяти то нет никакого смысла хранить копию этой структуры в разных горутинах или потоках не говоря уже о необходимости синхронизации частичных обновлений этой структуры между ними и опасности race condition. Для таких задач нужна именно общая память и параллельный доступ к памяти из разных потоков
0

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

+3
Структура хранится в одной горутине — выделенном «менеджере» этой структуры. А все остальные горутины получают доступ к ней общаясь по каналам с горутиной-менеджером

В этом случае решение превратится в однопоточное — только одна горутина (менеджер структуры) будет работать а все остальные будут только посылать инструкции. Понятно что при обработке запросов и формирования инструкций будут задействованы все ядра, но дальше все они будут выстраиваться в очередь и ждать пока один единственный поток их не обработает. Если на обновление структуры объектов глобальный лок еще оправдан для избежания race-condition, то инструкции на чтения структуры (базы данных или кеша) могут безопасно выполняться параллельно но не могут из-за такого вот подхода когда только одна горутина будет работать со структурой
0

Если эта структура — god object, который хранит все данные приложения — то да. Не надо так делать. А если таких структур куча (и у каждой своя горутина-менеджер) — то нет, не превратится в однопоточное.


Насчёт RWMutex Вы правы, он позволит распараллелить доступ. Но обычный Mutex точно так же выстроит всех в одну очередь, как и горутина-менеджер.

-1
В статье «Less is exponentially more» Роб Пайк почему-то относит обобщённые типы и наследование к «типизированному программированию» и говорит, что предпочитает композицию, а не наследование.

Наследование нужно для того чтобы оптимизировать логику декораторов которые в случае композиции будут создавать отдельные объекты в рантайме. Допустим у нас есть класс DBConnection объект которого представляет собой соединение с базой данных. Применяя композицию обычно создают отдельный класс Repository который представляет собой crud-операции с таблицами базы данных, который в конструкторе создает new DBConnection(...) и использует его для взаимодействия c базой данных. А вот применяя наследование вместо композиции класс Repository отнаследуется от DBConnection и добавит нужный код работы с crud. И здесь принципиальное отличие — в случае композиции при создании объекта Repository будет создано два объекта в рантайме (сам Repository и объект DBConnection) а применяя наследование — только один объект. А в случае если у на будет цепочка из 10 различных сущностей которые что-то добавляют и переопределяют то с композицией это уже 10 рантайм-объектов а с наследованием только один вне зависимости от длины этой цепочки (да хоть тысячу сущностей). В это и суть наследования — оно позволяет вынести в compile-time много работы экономя cpu-циклы и память
-13

Все Ваши проблемы синтетические. Как меня задолбал Хабр подобными постами.

0

В общем и целом статья отличная! Немного комментариев:


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

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


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

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


Трудно понять, какие типы реализуют конкретный интерфейс

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


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

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


Синтаксис := позволяет случайно «затенить» переменную.

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


Так что исключения в Go есть, он использует их внутри себя, но вам не разрешает.

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


Кошмар управления зависимостями

С появлением vgo есть веские основания надеяться, что через год (когда vgo станет официальным go) этой проблемы уже не будет. Причём не просто не будет, а всё будет работать лучше, чем сейчас в других языках!

0
Очень много полярных комментариев про Go, и меня даже сейчас смущает эта политизированность.
Но, всё же, я решил взять Go как рабочий язык.
1. Будем считать, что я слез с python (Go по духу близок, типизация это ооочень сильное послабление мне — невнимательному погроммисту)
2. Go (на мой исключительно субъективный взгляд) — это испорченный Oberon. А Oberon я действительно люблю. Имхо, очень продуманная вещь.
3. Стандартная библиотека почти во всём заточена под веб. Шифрование, шаблоны, обработка строк, изображения. Всё это работает с сетью, отображает результат в браузере (что тоже кросплатформенно, как и сам бинарник на выходе Go).
4. Производительность, всё-таки, не последнее, на что смотрит владелец ресурса. 20 серверов на python или один на Go — разница есть. Конкурентность вносит свою сложность (и коллеги из лагеря Erlanga убедительно показали, что в Go она сделана совсем не лучшим образом), но всё же, эффективность исполнения кода заставляет принять Go к сведению.
5. У Go таки есть странные решения. Типа, интерфейсов. Имхо, опасная штука с их автоматическим удовлетворением. Но стандартные типы никто не запрещал. Я пока профан в Go, так что посмотрим. Крики про отсутствие ООП мягко говоря — сильно преувеличены. Сделано своеобразно, но оно там есть.
6. В плане разработки у Go есть явные преимущества по причине наличия интересных IDE. LiteIDE, к слову. Качество контроля кода на Go я бы оценил где-то на 50-70% выше, чем в python на этапе разработки.

Ничего не скажу в духе книги Саммерфильда «ах, какая прелесть, ну просто паром писаю», но по сравнению с python — да, это безусловно шаг вперёд.
0
Если честно, я тоже считал это проблемой
А как быть с рефакторингом? Как IDE узнает нодо изменить имя метода или нет если в интерфейсе мы поменяли?
0
Если поменяли в интерфейсе, то менять надо однозначно. Интерфейс — это аналог абстрактного класса для методов.
0
Если поменяли в интерфейсе, то менять надо однозначно
А если Я нигде не передаю эту структуру там где ожидают этот интерфейс?
0
Если Вы не передаёте эту структуру, но этот интерфейс ожидается, значит тот интерфейс, который Вы меняете — должен наследоваться от интерфейса, который лежит уровнем ниже, и именно он должен быть ожидаемым интерфейсом. Поэтому, у гоферов есть правило: интерфейс должен быть как можно уже, интерфейсов должно быть много. А тот, кто создаёт тип от interface{} — таких бьют линейкой по рукам, пока не посинеют (руки).
+5
Хреновенький язык-то. Да и сам Пайк не такая светлая голова, как некоторые иные разработчики языков программирования.
Прошли мимо многих, придуманных до них, классных находок. Что приобрели — не понятно.
Аргументация, зачем так сделано, хромает.
И вся популярность языка обусловлена не высокой согласованностью фичей, не их разнообразием, не решением наболевших проблем других языков при сохранении того, что не было поломано, не прагматичностью при новаторском подходе, а PR-отделом гугла с их бабками, кучей статей, конференций и тп.
0
Главная фича этого языка — простота, и он отлично конкурирует скажем с питоном. Вообще язык отличный. А про PR от гугла как-то надуманно, зачем? Это же не коммерческий проект типа Java. Вам гугл не предъявит за использование языка в вашем проекте, как оракл.
+5
Почему простота — это фича, а не баг? Им простота понятно зачем, им проще компилятор ваять, а мне?
Был простой бейсик, и где он нынче?
Причем в го простота граничит с примитивностью.
Может быть, хотели компенсировать тулингом, как в яве в итоге получилось. Но при это замутили дактайпинг, который с тулингом не особо хорошо дружит. Странно.
Почему вы с питоном сравниваете статически типированный язык? Любой скрипт при таком сравнении всосёт.
И у вас неверные сведения о яве, есть OpenJDK, который почти идентичен оракловскому хотспоту, javaFX только нет.
0
Потому что вы сейчас пишете не на асемблере, и причина сложность, вы предпочитаете что-то более простое и удобное в работе. Go такой же простой в использовании как питон, но производительнее, вот почему он де факто на рынке конкурирует с питоном, там где раньше использовали бы питон (тот же веб, сервисы) сейчас пишут на Go. При сопоставимой простоте/сложности вы получаете бонусом производительность.
+3
Потому что вы сейчас пишете не на асемблере, и причина сложность, вы предпочитаете что-то более простое и удобное в работе.
Ну так ведь наоборот, высокоуровневые языки сложнее. Не путайте пожалуйста сложность самого языка (количество фич в нем, абстракций и т.п.) и сложность написания кода на этом языке. Так-то Brainfuck вообще архипростой, всего 8 символов, 1 тип данных… Красота, а не язык!

Go такой же простой в использовании как питон

Ох… ну раз уж я тут в другой ветке поднял тему сортировок… давайте сравним еще раз. Пример из статьи:
оimport "sort"

type Person struct {
    Name string
    Age  int
}

// ByAge implements sort.Interface for []Person based on the Age field.
type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }

func SortPeople(people []Person) {
    sort.Sort(ByAge(people))
}

И вот аналогичный код на Python (даже с тайпхинтами!, без них еще проще):
import typing

class Person(typing.NamedTuple):
    name: str
    age: int

def SortPeople(people: typing.List[Person]):
    people.sort(key=lambda p: p.age)

А теперь представим, что понадобилось сортировать еще и по Name (в зависимости от выбора пользователя)… А потом добавилось еще 5 новых полей, по которым тоже надо сортировать…
0
А с удобной compile-time рефлекшном можно и такое забацать, а потом писать
AssertEx.AllPropertiesAreEquals(expected, actual)

Даже если авторы компилятора забыли это написать. Ах да, пользователи языка — смерды, и не имеют права на написание обобщений…
0
Ну справедливости ради такое можно и в Go замутить. Сигнатурка будет не ахти func (a, b interface{}), но сделать приличный репортинг дифа технически вполне можно. Без дифа даже из-коробки имеется reflect.DeepEqual.
0

Я Go плохо знаю. interface{} в данном случае должен быть интерфейсом, поля которых мы сравниваем? Если да, то проверит ли он в compile time что a и b реализуют этот интерфейс, причем для a он является наиболее специфичным?

+1
Ну, тогда это совсем не то. В том-то и дело, что пример который я дал один раз строит по типам лямбду, а потом просто её вызывает с нулевым оверхедом. А Go вариант больше похож на старый-добрый рефлекшн.
0
В том-то и дело, что пример который я дал один раз строит по типам лямбду, а потом просто её вызывает с нулевым оверхедом
А в чем профит если не секрет? Дабы юнит тесты выполнялись на пару ms быстрее? :)

Go вариант больше похож на старый-добрый рефлекшн.
Это и есть старый добрый рефлекшн.
+2
А в чем профит если не секрет? Дабы юнит тесты выполнялись на пару ms быстрее? :)

Ну, отчасти для образовательных целей, отчасти да, чтобы было быстрее. Т.к. эта функция вызывалась по сути в нескольких сотнях тестов для проверки тысяч объектов в каждом. Экономия даже пары десятков секунд на выполнение тестов на ровном месте это уже неплохо, как мне кажется.
0
Сравнивал. Например получить свойство через рефлекшн в 1000 раз дольше, чем получить его напрямую (линк). Если у нас несколько сотен тестов (возьмем 250), в каждом 1000 объектов, у каждого из которых 5 свойств, которые мы сравниваем парами (еще х2), то это 2500000 вызовов. Используя данные по ссылке, это займет 0.53 секунды при прямом вызове, и 482 секунды (8 минут) через рефлекшн. Как по мне, разница существенная, даже если тесты гоняются параллельно.
0

вы сравниваете С# реализации, а не с Go reflect.DeepEqual. Код нужно скомпилировать, заранить тесты. Насколько существенная разница будет для Go?

+3
Ну я не проверял, но думаю, что вряд ли Go каким-то магическим образом сильно отличается, поэтому можно принять данные по шарпу с точностью до порядка. Если вы считаете иначе, то прошу дать ссылку на сравнение, потому что у меня после беглого гугления информации не нашлось.
+3
Можно подумать в Go рефлексия молниеносно быстрая.
Вот например баг. Там указывают вполне реалистичные оценки
reflect.Value.Call is ~65-80x slower than other invocation types


Как я понимаю PsyHaSTe не призывал так делать для Go (для и шарпа походу больше для just-for-fun сделал, что есть респект). В Go такое банально не сделаешь — ну нету в нем рантаймовой генерации байткода / компиляции на лету…
0

если это реально узкое место, то можно и код генерить. Мне интересно сравнить всю цепочку

+1
Я использовал информацию, предоставленную в статье. Если у вас есть обоснованное сомнение в этих выводах, то я с радостью почитаю статью-ответ. Я не трогал каких-то других особенностей языка, о которых не знал.
+1
Справедливости ради, код выше переписывается так:

import "sort"

type Person struct {
	Name string
	Age  int
}

func SortPeople(people []Person) {
	sort.Slice(people, func(i, j) bool {
		return people[i].Age < people[j].Age
	})
}


и разница внезапно становится не столь значительной.
+1
Почему вы с питоном сравниваете статически типированный язык? Любой скрипт при таком сравнении всосёт.
PHP с его type declarations будет построже, чем Go.
+1
Хотелось бы чтобы место go занял d. Но без бабок и pr это сейчас или невозможно или практически невозможно.
+1
Я думаю что хорошим пиаром для языка будут сильные проекты на нем. Сейчас очень хайповый и популярный проект Докер, он сам по себе и пиарит Go
0
Pr докера это отдельная тема. На d есть прекрасный проект vibe.d брал типы в разных бенчмарках. И тем не менее все ещё никому не нужен
0
Не понимаю, почему на выбор языка программирования вообще должен влиять хайп. Мы инженеры, а не модельеры какие-нибудь.
Рациональный выбор нам, по идее, не чужд.
Разбираться в дизайне языков программирования, уметь сравнивать их, и выбирать под задачу наиболее подходящий инструмент — не это ли части нашей работы?
+1
Потому что хайп влияет на то, сколько людей уже занимаются этим языком, а количество занимающихся этим языком людей влияет на количество библиотек и количество вопросов на SO.

Да и, в конце концов, больший хайп означает, что большее количество людей могут решать проблемы на этом языке. Это я могу и вы, судя по некоторым комментам, можете прочитать такой ответ на вопрос о том, почему totaliy checker иногда странно себя ведёт, как будто бы не согласуясь с тайпчекером, но требовать этого от каждого инженера — это перебор.
-1
Вы правы. Аргументация необходимости фич — откровенно слабая. Но теперь представьте себе: golang — замена python. Разве это плохо? Приведённый пример с типизацией для python — не серьёзный. Никакой типизации в нём нет.
В golang вполне себе настоящая.
-3
Go подкупает простотой и минимализмом, он просто вынуждает всех писать простой, понятный, линейный код без всяких извратов в стиле «смотри как я могу!». После ентерпрайзных проектов на C#, с огромной complexity и купой абстракций, Go стал прям глотком свежего воздуха. Но потом приходит осознание того что разруха в головах, и на том же привычном C# можно писать простой и понятный код. Потом попробовал в деле .NET Core (кроссплатформенный, сильно похудевший, переработанный .NET для тех кто не знает), и знаете, разработка очень похожа на Go, только с мощностью C# без компромиссов и нормальным тулингом. Единственная проблема это командная разработка — если ты проникся простым и понятным кодом и можешь себя контролировать не использовать фичи C# не к месту, коллеги часто такое воротят что глаза на лоб лезут. На GO им делать это было бы сложнее.
-1
Go заметно проще других языков, но он далеко не прост и не минимален.
С# лично мне не нравится своим синтаксисом, но и в Go можно написать так, что глаза сломаешь. Тут немного легче при принудительном использовании gofmt. Стиль везде один, да.
Хотите глоток свежего воздуха? Вот прям настоящего свежего воздуха? Поковыряйте на досуге BlackBox/Component Pascal и Oberon-07 — особенно последний покажет вам минимализм и простоту.

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

У Go есть свой путь, безусловно. Но пИсать паром — ну нет, пока ещё рановато. Вполне себе обычный, предсказуемый ответ на злобу дня.
+1
Поковыряйте на досуге BlackBox/Component Pascal и Oberon-07 — особенно последний покажет вам минимализм и простоту.

Brainfuck ещё минималистичнее и проще.
0
Брайнфак не выполняет главное указание, вынесенное в эпиграф сообщения об Обероне: «Сделай максимально просто, но не примитивно. А. Эйнштейн».
Оба перечисленных языка ровно такие: просты, но не примитивны.
0
Осталось разобраться с какими-нибудь более-менее формальными критериями простоты, примитивности и прочего.
0
Ну, например.
Форма объявления с присвоением в голанге — целых ТРИ!
В Обероне — одна. Не могу сказать, что ух какой контекст, но тем не менее.
В голанге есть форма присвоения значения константам iota. С возможность автоматических сложных выражений — ух. Но на сколько iota реально востребована?
В голанге форма привязки функций к типам спёрта из Оберона. Отличается множественными возвращаемыми значениями (при явном указании — именованными значениями), в Обероне — возвращаемое значение — одно. Но встретить просто return без возвращаемого значения в голанге… Немного вводит в ступор.
В голанге нужно явно получать адрес переменной при передаче по ссылке. Оберон это делает автоматически и голова не болит.
В голанге понятие пакета сделано странно. Обероновское MODULE куда проще и понятней. Экспорт в голанге большой буквы, и сокрытие с маленькой — ну это какая-то фигня. В Обероне в конце имени ставь звёздочку — и вот тебе экспорт.
В голанге, не смотря на то, что ООП слизано с обероновского — интерфейс штука скользковатая. В Обероне просто нет интерфейсов. В Компонентном Паскале есть абстрактные классы, абстрактные методы, расширяемые методы, классы с ограниченным расширением, частично абстрактные классы, ненаследуемые классы, и… Вроде всё. Но при этом Компонентный Паскаль проще голанга раза в два. Там негде и нечем стрелять себе по ногам.
Короче, голанг, лучше питона. Но он не прост и не самый логичный язык.
0
Форма объявления с присвоением в голанге — целых ТРИ!

Кто третья?


Но на сколько iota реально востребована?

Вполне востребована и выполняет свою функцию: уменьшает количество ошибок, которые были бы при ручном объявлении перечислений.


Но встретить просто return без возвращаемого значения в голанге…

Да, на мой взгляд это лишняя фича.


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

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


В голанге понятие пакета сделано странно.
Экспорт в голанге большой буквы, и сокрытие с маленькой — ну это какая-то фигня.

Вкусовщина.

0
Кто третья?

1. var i int
2. for i int = 0
3.for i:=0
Вполне востребована и выполняет свою функцию: уменьшает количество ошибок, которые были бы при ручном объявлении перечислений.

И как часто она используется?
Т.е.
const(
a int = 0
b int = a +1
)

это будет много ошибок?))

Да, на мой взгляд это лишняя фича.

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

А в Обероне компилятор это делает во всех случаях, а если такое поведение не верно — значит компилятору это надо указать явно. Но такие случаи — большущая редкость.

Вкусовщина.

Это не вкусовщина. Это явный промах. Забылся, шифт не отжал и получи косяк.
Ну это ладно. Победить можно, а вот система пакетов (уже упомянутая) — вещь куда более спорная. Была заявка на модульность, а получилось как-то не очень. Для поддержки больших систем — это важно.
0

Их только две: var и :=. Вторая внутри for (а так же if и switch) ничем не отличается от использования вне этих конструкций.


это будет много ошибок?

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


Забылся, шифт не отжал и получи косяк.

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


Была заявка на модульность, а получилось как-то не очень.

Вообще-то нет. Заявку на модульность делают только сейчас, в vgo. До этого заявка была только на пакеты, т.е. по сути на namespace — это нужно для модульности, но это не она.

0
Их только две: var и :=. Вторая внутри for (а так же if и switch) ничем не отличается от использования вне этих конструкций.
А как вы относитесь к 'for ... := range ... {'. Это отдельная форма присвоения, это вообще не форма присвоения, это частный случай ":="?
0

Это не частный случай, а абсолютно обычный. Вы же не считаете a := f() частным случаем a := 5?

-1
На самом деле отличия есть, вот смотрите.

a := "abc"
Тип abcstring, тип a — тоже string.

for a := range "abc"
Тут переменная a имеет тип int.

for _, a := range "abc"
А вот тут тип уже int32 (т.е. rune).
0

А в чём отличия-то? range от строки возвращает не строку, а индекс символа и сам символ. Вы создаёте новую переменную с тем же именем и присваиваете туда возвращённое range значение.


Оператор := работает здесь ровно так же, как и в любом другом месте:


  • требует чтобы слева была хоть одна новая переменная,
  • затеняет существующую переменную в новой области видимости при необходимости,
  • создаёт новые переменные,
  • присваивает значения всем заданным переменным.
0
Вы не можете использовать ":= range" вне цикла.
Если присмотреться чуть внимательнее, то можно заметить, что это вообще не отдельная операция ":=", а часть синтаксиса for-each.

В спеке он, кстати, описывается в отдельной секции синтаксиса циклов, а не в секции оператора :=.
0

Всё верно, но мне казалось мы тут обсуждаем количество разных вариантов объявления переменных — 2 их или 3. Их 2. А range это часть for и к этой теме вообще отношения не имеет.

0
И как часто она используется?

не часто, но удобная когда нужно сгенерить разные последовательности.
Можно же генерить с любым шагом или, например, n^2 последовательности

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

в Go нету передачи по ссылке, только по значению.

0
В любом языке где есть указатели или ссылки — возможна и передача по ссылке. Вопрос лишь в уровне языковой поддержки.
+1

в Go нету ссылок, есть только указатели, которые передаются по значению.

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

значение, на которое указатель указывает не передается по ссылке. Можно сделать самому явно дереференсинг уже в теле функции. Передачи по ссылке в Go нету.

0
Если мне в Go (или в Си) нужно передать что-то по ссылке — я беру и передаю указатель. Да, с точки зрения языка это обычная передача указателя по значению — но программист способен оперировать более высокими уровнями абстракции.
0

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

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

нет, в Java, насколько я знаю, объекты передаются по ссылке. Можно ли в Java сделать, например, вот так в Go:


package main

import (
    "fmt"
)

type bar struct {
    k string
    v int
}

func main() {
    b := bar{k: "1", v: 1}
    foo(&b)
    fmt.Print(b)
}

func foo(b *bar) {
    b2 := bar{k: "2", v: 2}
    *b = b2
}
0
нет, в Java, насколько я знаю, объекты передаются по ссылке

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


Можно ли в Java сделать, например, вот так в Go:

Если в b в main напечатается k: 2 и v: 2, то нельзя. Плюс это означает передачу параметра b по ссылке.

0
Передаются не объекты, а переменные.

Простите, что????


Передаются они в джаве только по значению.

Я не уверен, просто возможно, что переменные в Джаве изначально содержат ссылку на объект. Вот например:


Object obj = new Object()

Тут obj хранит ссылку или сам объект (значение)?


Если в b в main напечатается k: 2 и v: 2, то нельзя. Плюс это означает передачу параметра b по ссылке.

fmt.Print(b) выведет k: 2 и v: 2. Это не ссылка, это указатель передали в другую функцию по значению. Указатель содержит адрес, это просто значение тип 0x...... Если скопировать это значение у другую переменную — тогда она тоже будет указывать на тот же объект.
Тип в функции func foo(b *bar)*bar указатель, причем типизированный указатель. Есть еще unsafe.Pointer.

0
Тут obj хранит ссылку или сам объект (значение)?

В переменной obj — указатель на объект.


fmt.Print(b) выведет k: 2 и v: 2.

Каким образом двойки попадут в b?


  1. Будут скопированы из b2 в объект b?
  2. Или в переменную b попадёт значение из переменной b2 и таким образом b станет указывать на объект b2?

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

0
Я уже устал объяснять — передается указатель по значению, потом перезаписывается объект, на который указывает указатель.

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

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

насколько я понял, в Java переменные типа Object obj = new Object() являются ссылочными переменными.

0

Нет, точно такие же в С++ — указатели. Вот совсем точно такие же, один в один. Аналога референс переменных из C++ в Джаве нет.

0

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

0
Если в go нет ссылок, то как же происходит РАЗЫМЕНОВАНИЕ??))
Разыменование ссылок в C++ не требует специального оператора.


В некоторых языках помимо этого оператора предусмотрен ещё и оператор явного удаления переменных из памяти. Обе эти операции часто принимают форму встроенных подпрограмм (функции malloc и free в Си, операторы new и delete в C++ и т. п.).
А это уже из второй статьи:

А вот опять цитата из первой статьи:
Java и C#
В этих языках понятие указателя отсутствует, а вместо него используется понятие ссылки. Разыменование ссылок и взятие адресов объектов для присваивания их ссылкам не требует специального оператора.

Это получается, в Сисярп и Яве переменные не типизированы??

Нет явного разделения с такой кашой на «ссылки» и «указатели». И википедия в двух статьях вам это подтверждает.
0
Если в go нет ссылок, то как же происходит РАЗЫМЕНОВАНИЕ??))

РАЗЫМЕНОВАНИЕ чего?


В Go нету ссылок, есть указатели.

+1
Вы это мне пишите?)) Задайте вопрос википедии, где разыменование используется и в статье «Ссылка», и в статье «Указатель».
В Go нету ссылок, есть указатели.

А вот Вы знаете, в книге самого Роба Пайка на стр. 270 используется слово «ссылка», причём, в значении «ссылка на структуру». А потом на стр. 323 слово ссылка используется в значении «ссылка на кэш», стр. 340 — «ссылка на член пакета», предметный указатель — «Ссылка — стр. 33». А на странице 33 написано буквально следующее: «Отображение является ссылкой на структуру данных», при чём КУРСИВ — прям из книги.
Так что не берите на себя много. ;-)
+1
Вы написали что? «Ссылок нет!». Я открыл книгу, и продемонстрировал Вам, что ссылки есть. Я прекрасно понимаю, что переводчик мог и ошибиться, но тем не менее.

По приведённой ссылке я так понял, что речь идёт не про ссылки и указатели, а про ссылки и указатели. В смысле, псевдоним в С++ (содержит физический адрес) — тоже самое, что и переменная по ссылке в голанг, и два-три-десять псевдонимов-адресов будут совпадать по цели в памяти.
Что я не понял: фактически в примере на С++ создаются три переменных, указывающих на одну и туже переменную. Может быть, я не правильно понимаю запись в С++, но как-то странно ожидать, что их содержимое (адрес) не будет совпадать?..
А в Go — именно сами переменные создаются, которые, РАЗУМЕЕТСЯ, не могут быть в одной ячейке памяти.

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

Так что, имхо, пример несколько неудачный. Я бы не стал на Вашем месте на него ссылаться))
0
речь идёт не про ссылки и указатели, а про ссылки и указатели.

Что?


Что я не понял: фактически в примере на С++ создаются три переменных, указывающих на одну и туже переменную.

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


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


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

0
Что?

Именно что написал, то и есть.

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

И все три находятся в одной ячейке памяти? Судя по ссылке и намёкам автора, дело обстоит именно так. Я бы очень не хотел, что бы автор так считал.

0

Это ссылочные переменные. Там же есть код, скопируйте и запустите у себя. Адрес всех трех переменных будет один и тот же. Потому что b и c это ссылки на a.
В Go такое не возможно.


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

0
Потому что b и c это ссылки на a.
В Go такое не возможно.

Что значит невозможно?? Там же ссылки и показаны на Го? Или Вы хотите сказать, что в С++ переменные-ссылки расположены в одной ячейке памяти?)))
0

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

0
Вы слышите о чём я? НЕ МОЖЕТ быть три переменных, хоть в брайнфаке, которые находятся в ОДНОЙ ячейке памяти!!! Хоть ссылки, хоть указатели.
0

Там одна переменная и две ссылки.
Давайте я сделаю это за вас:


#> test  % cat main.cpp                                                                                                                                                             
#include <stdio.h>

int main() {
        int a = 10;
        int &b = a;
        int &c = b;

        printf("%p %p %p\n", &a, &b, &c);
        return 0;
}
#> test  % gcc main.cpp -o main                                                                                                                                                     
#> test  % ./main                                                                                                                                                                   
0x7fff53584858 0x7fff53584858 0x7fff53584858
0
Ну а ссылки, что? Разве не переменные?
Я этот кусок видел в том сообщении по ссылке.
И результат работы тут мне понятен (если я правильно вообще понимаю С++).
Я спрашиваю про другое: вот эти три ссылки — они В ОДНОЙ ЯЧЕЙКЕ памяти лежат?
printf("%h %h %h\n", a, b, c);

^ Вот эту строчку добавьте?!
0
Ну а ссылки, что? Разве не переменные?

Это ссылочные переменные.


Я спрашиваю про другое: вот эти три ссылки — они В ОДНОЙ ЯЧЕЙКЕ памяти лежат?

Там одна переменная (которая храниться в памяти) и две ссылочные переменные (что как бы не совсем переменнае). Вот вам почитать:
https://isocpp.org/wiki/faq/references#overview-refs


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

0
Хм. Судя по тексту, в С++ это — константа, которая вычисляется на этапе компиляции, без выделения отдельной ячейки под хранение константы, с использованием синтаксиса объявления ссылочной переменной. Этакая нечленораздельная оптимизация.
Я правильно понимаю, что если сделать где-нибудь в цикле
b = malloc(uint);
b = &a;

таки это будет создана ссылка ровно так же, как и в golang?
0
В голанге нет передаче по ссылке? Это вы плохо сейчас подумали.
вот вам функция, требующая ссылку:
func (self *TDive) Get(name_ *TName)(num_ *TNum){
....
}

Тут аж три ссылки требует. А вот вам взятие адреса:
a := &person.Name

Адресной арифметики — действительно нет. Если не пользовать опасные средства — тип ссылки поломать нельзя.
Если вы под ссылкой имеете в виду «указатель» — так это то же самое.
И ссылку внутрь функции передать тоже можно. Особенно, если она оформлена типом.
-1
В голанге нет передаче по ссылке?

Нету, в вашем примере идет передача указателя по значению. self *TDive — это указатель. Содержит (хранит в памяти) адрес указывающий на объект. Это просто значение. Оно хранится в памяти, потому можно даже получить указатель на эту переменную (указатель на указатель).
Разберитесь, что такое ссылка и что указатель, и почитайте что в Go.

+1

Я, конечно, люблю Go, и люблю называть вещи своими именами, даже очень. И я читал http://spf13.com/post/go-pointers-vs-references/. Но, по-моему, Вы всё-таки перегибаете палку. Если разработчик писал на плюсах, где есть и то и другое, то он, предположительно, разбирается в отличиях и не запутается с указателями в Go. Всем остальным — пофигу. У меня до Go в опыте разные языки, от ассемблера до перла, но плюсов нет, и ни в одном из моих языков ссылок как в плюсах не было — зато во многих были указатели, где с адресной арифметикой, где без. И называли их в половине случаев — ссылками. По настроению, в основном. Могли в одном и том же предложении одну и ту же переменную назвать и ссылкой и указателем. И никогда это не вызывало проблем с пониманием. (Более того, в перле, кстати, что-то подобное ссылкам плюсов таки есть — только называют их алиасами, и реализованы они не столько в самом языке, сколько в отдельной библиотеке.) В общем, называть вещи своими именами важно, но здесь и сейчас Вы — перегибаете.

-2

Потому что это ведет к неправильным выводам, что в Go есть передача по ссылке. Нету, только по значению.

0

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

0

Ссылка и указатель это не одно и то же.
map это структура (как и слайс) которая содержит указатель, потому такое и поведение.

+1

Спасибо, я в курсе как устроен map. Но, ещё раз попытаюсь объяснить, правильные термины важны не сами по себе, а потому что они проясняют ситуацию. В нашем случае терминологически правильное заявление "map передаётся по значению" ничего не проясняет, а наоборот, запутывает. Разница между передачей по значению и по ссылке/указателя важна не потому, что описывает внутреннее устройство языка, а потому что показывает программисту чего ему ожидать — сможет ли вызванная функция изменить переданное ей значение, или нет. А когда термины вроде правильные, только ни разу не помогают понять что происходит — они бесполезны. А как только они становятся бесполезны — все становится плевать, каким словом что "правильно" называть.

+1
Да, все всегда передается по значения. Это правда, но вот в значении может быть неявный указатель:
1. Встроенные типы (slice, map, chan) хранят внутри себя указатели. Так что, например, map-ы семантически передаются таки «по ссылке»;
2. При заворачивании типа в интерфейс тоже «под капотом» хранится указатель, что тоже по сути может приводить к «передаче по ссылке».
0

Мне вот просто любопытно — зачем Вы подчёркивания используете?

-2
Это моя личная странная привычка. Параметры функции примерно вот так и выглядят — подчёркивание в конце. Локальные переменные либо подчёркивание впереди, либо префикс «л». Соответственно, глобальные переменные — не имеют подчёркиваний и префикса «г» — глобальный. Оно и так понятно. Хотя, может как раз глобальные переменные стоит помечать — их меньше.
Более того, переменные err — я даже нумерую.
Таким образом я гарантирую себе, что я понимаю, про какую именно переменную идёт речь и нет перекрытий в области видимости.
По-моему, достаточно дешёвое решение для получаемого уровня надёжности кода.
+2

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

0
Как локальная переменная, да ещё и пронумерованная может устроить затенение?? А если учесть, что я не объявляю переменные где попало, а только в секции var — мне это вообще мало актуально))
Линтер в голанге, например, невозможно не использовать. Приходится ему правила игнорирования прописывать.
Что касается «ругани на подчёркивания», ну не знаю… Если кому-то не нравится — так я не держу. Отпускаю на все четыре стороны, и пусть ищут работу где хотят. Нет проблем.
(* Но пока таких случаев не было *)
0
Я тут почитал и понял, что хаскель — простейший язык.

Форма объявления с присвоением в голанге — целых ТРИ!
В Обероне — одна. Не могу сказать, что ух какой контекст, но тем не менее.

В х-ле нет объявления и присвоения, вы просто пишете уравнения. Форма лишь одна.

В голанге есть форма присвоения значения константам iota. С возможность автоматических сложных выражений — ух. Но на сколько iota реально востребована?

И правда, наркомания какая-то. С тайпклассом Enum и синтаксисом вроде [0..10] (или [0..] для бесконечного списка) всё сильно проще и очевиднее. И да, востребовано.

Отличается множественными возвращаемыми значениями (при явном указании — именованными значениями), в Обероне — возвращаемое значение — одно.

В х-ле у любой функции и аргумент один, и возвращаемое значение одно. Проще некуда!

Но встретить просто return без возвращаемого значения в голанге… Немного вводит в ступор.

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

Ну и да, понятия возврата из функций там тоже нет, потому что функций тоже нет, есть только уравнения (как просто-то!).

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

Ну да, неявное же лучше явного.
В х-ле вообще нет ни адресов, ни ссылок. Красота!

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

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

В голанге, не смотря на то, что ООП слизано с обероновского — интерфейс штука скользковатая. В Обероне просто нет интерфейсов. В Компонентном Паскале есть абстрактные классы, абстрактные методы, расширяемые методы, классы с ограниченным расширением, частично абстрактные классы, ненаследуемые классы, и… Вроде всё. Но при этом Компонентный Паскаль проще голанга раза в два. Там негде и нечем стрелять себе по ногам.

В х-ле ООП нет. И интерфейсов тоже нет. И абстрактных, неабстрактных, наследуемых, ненаследуемых классов нет. Есть просто тайпклассы, и всё.

Какой простой язык-то, оказывается!
-3
Возможно. Но когда я смотрю на его синтаксис — я не понимаю что делают элементарные конструкции. Даже ассоциаций не возникает.
Зачем жрать кактус, когда можно его не жрать?
+1
Какие из синтаксических конструкций вам непонятны? Объявление типа функции? Определение функции? Конструкция if/then/else? Определение типа данных? Паттерн-матчинг?
-2

Мне все синтаксические конструкции непонятны. Они неочевидны, они перпендикулярны общепринятым обозначенияс, они не следуют принципу наименьшего удивления.
Второй момент, который мне не нравится: создаётся дополнительная прослойка семантического разрыва между тем, что я вижу (как я привык мыслить) и тем, что я делаю. Это искусственное усложнение во имя чистой науки меня вообще никак не радует. ООП, например, в С++ (как и сам весь С++) это очередной перегиб, но попытка создать язык, имитирующий математический подход — такой же перегиб.
Истина где-то между крайностями.

0
Мне все синтаксические конструкции непонятны. Они неочевидны, они перпендикулярны общепринятым обозначенияс, они не следуют принципу наименьшего удивления.

Не знаю, сам синтаксис мне как-то очень хорошо и просто зашёл в своё время.

А принцип наименьшего удивления — это скорее про внутреннюю консистентность. И там с ней как раз всё в порядке, особенно по части синтаксиса (у меня есть претензии к иерархии тайпклассов, например, но это совсем другой вопрос).

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

Это вопрос привычки. Мой отец, физик, никак не мог понять, что значит «вернуть значение из функции» — вот функция f(x), вот y=f(x), что там куда возвращается? Да, можно спуститься на уровень алгоритма вычисления функции, но не со всеми функциями так можно сделать, да и смысл-то не в этом. Хаскелевский подход в смысле интерпретации функций тупо как кучи уравнений отцу тоже хорошо зашёл.

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

Это искусственное усложнение во имя чистой науки меня вообще никак не радует.

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

Ну и мне вот лично неочевидно, что проще, понятие монадного трансформера или какой-нибудь там SOLID пополам с MVC.
0

Вы всё верно написали, и можно согласиться, и видимо дело привычки, но.
Вот лично моё восприятие таково, что когда я вижу синтаксис, который на мой взгляд неудачный — лучше застрелиться. Функциональный язык, типа Хаскеля — вот как раз попадает в эту группу.
Был бы я вами — ну, наверное бы использовал)

0
Ну, это весьма субъективный вопрос, так что я бы говорил, наверное, «который мне не нравится/непонятен», а не «неудачный», а так да, конечно.
Только полноправные пользователи могут оставлять комментарии. , пожалуйста.