Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
From(students).
Where(func (s T) (bool, error){
return s.(*Student).age >= 20, nil
}).
Where используется делегат и (б) в этом делегате входной параметр приводится к нужному типу?Import your []*Student.
Find those over 20. Note T is an alias for interface{}. So we make type assertion to our input type.
Where — делегат. Это ведь так?fruits.AsQueryable().Where(fruit => fruit.Length < 6);
fruit => fruit.Length < 6
fruits.AsEnumerable().Where(fruit => fruit.Length < 6);
Where — делегат (анонимная функция), которая будет скомпилирована в исполняемый код вместе со всем остальным кодом вокруг, и выполнена .net-рантаймом в момент итерации.fruits.AsQueryable().Where(fruit => fruit.Length < 6);
Where — выражение (AST), которое в момент компиляции будет только построено, а вот в рантайме будет проанализировано и выполнено тем способом, который нужен провайдеру, лежащему под fruits. Например, преобразовано в предикат WHERE Length < 6, если провайдер поверх БД. Или в $filter=Length lt 6, если провайдер поверх OData.Не знал про такое — но это свидетельствует скорее о умном компиляторе IL кода, нежели выразительности самого языка.
LambdaExpression(CompareExpresssion(MemberAccessExpression(ParameterExpression("fruit"),"Length"), LessThan, ConstExpression(6)))). А дальше это AST уже разворачивается исполняемым кодом.Каналы — удобно, но мне они нужны для параллельной обработки массивов данных. В C# это решается проще, Parallel.ForEach и вперёд
$ go run check.go
Count 10000; 25.437204715 - 25.484347422
Count 20000; 25.437177393 - 25.605745478
End
func f(n int := 0) {
// pass
}
— не такие большие сообщество и база знаний. Не всегда удается найти готовые решения или ответы.
перевод статьи опытного разработчика о его опыте практического применения Go.
Итак, прошел год с тех пор, как я начал использовать Go.
Вань! Ты посмотри какие клоуны — рот хоть завязочки пришей!
По вашему невозможно быть опытным разработчиком без опыта использования Go?
Обсуждать вкус устриц хотелось бы с теми, кто их пробовал.
или в этом… в DevOps-се? ;-) ;-)Вот есть такие ребята. У них всё на Go написано, номады всякие с консулами. Логично, что люди, которые крутятся в этой кухне, пытаются пробовать Go, потому что авторы Go его для этого самого и позиционируют. Системный язык из Go не получился, остался пресловутый web и DevOps. Кто по вашему должен составлять мнение о Go в таком случае, бородатые системные программисты?
Под «системным языком» можно понимать что угодно, но есть чёткие определения, что такое «прикладное ПО» и «системное ПО».
Q: You mentioned initially having the clear target of being a systems language was important. Is that still the target or has the target changed?Создатели языка сами позиционируют его как язык общего назначения, на таких языках обычно не пытаются всерьёз писать драйверы устройств, ядра операционных систем или прошивки для микроконтроллеров, но для написания достаточно низкоуровневого server-side кода он вполне подходит.
A: At this point, we really think of Go as a general purpose language. That’s also how people use it. It’s being used across the spectrum, and so that’s how we feel at this point.
Q: Most users of Go seem to be server-side. Do you think one way to make Go more mainstream is to attract more client-side developers.
A: The original design was not a standard general purpose language; it was a systems server-side programming language. There’s no ui package, for instance. Now that it’s general purpose, we would really like a ui package, but it’s a lot of work to come up with something that’s cross platform. We could use a lot of experts from the Go community here.
Очевидно, имеется ввиду не столько «сетевое», сколько «многозадачное с долгими ожиданиями событий для продолжения задач», когда создавать по потоку на каждую задачу — дорого, а делать всё в один поток — медленно.Это само собой.
Многие языки поддерживают её в той или иной мереДа, но не так хорошо: NodeJs, Python, D, Rust, C# — там либо async+await либо yield либо callback-hell. Хотя в Python есть gevent, но результат выходит гораздо медленнее чем на Go. Вот Erlang — конкурент, но он мне не очень нравится, может ещё какой-то язык подскажите? Вот Rust был бы не плох, но там нет микро-тредов либо с ними беда. Поэтому для меня решения на Go в качестве «сетевых тулзов» на первом месте, (для веба и тяжелых расчетов он уступает питону, с++ и другим).
Не вижу принципиальной разницы междуРазница есть, в await и yield, ф-ии и библиотеки разделяются на 2 типа, при этом есть проблемы вызова одних типов из других. В go только один тип, поэтому такой проблемы нет и не нужно городить «синтаксический мусор».
Подсказать могу — D на голову лучше Go.В нем тот же yield, а С/С++ он не заменит из-за скорости (а если скорость не нужна тогда можно заюзать хоть питон).
дизайн крутится вокруг одной единственной фичи, а остальные не реализуются с отпиской «это сложно в реализации поэтому не нужно»Согласен, но это совсем другая история :).
1. Один тип легко преобразуется в другой.Это не так, попробуйте преобразовать Django в async+await…
1. Там те же волокнаВот это уже получше, попробовал — не плохо. Но раздвоение сохраняется, например vibe.d дублирует функционал стандартной библиотеки. Хотя для мелких проектов это не страшно. Надо будет проверить на сколько fiber быстрее/медленнее чем корутины от го.
2. С чего бы ему быть медленней,Где то на dlang сайте вычитал — они рекомендуют использовать C если нужна бо'льшая скорость, хотя судя по мелким тестам пользователей он почти не отстает от c/c++.
Беглое гуглениеЭто не то, не микро-треды, я специально написал «async+await», можете не гуглить, за это никто не возьмется.
А он-то тут при чём?Я его попробовал в качестве асинхрононнго фреймворка работающего с сетью, дак вот он частично дублирует стандартную либу, про что я и говорил.
Fiber.yield возвращает с любого уровня вложенности вызововКстати в этом есть плюс — мы контролируем когда нам переключится, значит для глобальных/общих объектов в пределах потока локи не нужны в отличие от Го.
И минус — вы должны четко понимать, кто за кем следуетДа там полно минусов, поэтому горутины из Го — это значимая фича.
В Go варианте вывод какой-то странный — по две итерации каждой горутиной.Возможно они в разных потоках, при этом в одной горутине принт срабатывает чуть позже, а после sleep чуть раньше, и выглядит как будь-то они «слипаются».
, дак вот версия на golang в 3-4 раза производительней (что не удивительно)
Питон медленнее Го, но не в три-четыре разДа, не в три-четыре, а больше, если сравнивать скорость исполнения питон-байткода.
Пустые циклы очень хорошо оптимизируются компиляторамиТакие циклы обрезаются умными компиляторами, но это не тот случай.
Математику в питоне или не считают или считают с использованием специализированных пакетов типа numpy, насколько я знаю.Да, питон достаточно быстрый для своих задач за счет того что многие модули написаны на C/C++.
Скажите сколько ядер на машине2, но это не имеет значения для данного теста (Во всех тестах я делал с ограничением в одно ядро и без).
но это не тот случай
Во всех тестах я делал с ограничением в одно ядро и без
очень похоже именно на этот случай.Если бы цикл вырезался, то приложение не задерживалось бы на 0.4 сек (на 4 сек при увеличении цикла в х10 раз). Для уверенности можете какую-нибудь сложную математику протестировать.
что бы Go не форкался автоматом по числу ядер?Это управляется с помощью GOMAXPROCS
Для уверенности можете какую-нибудь сложную математику протестировать.Математику не стоит, она очень плоха в питоне из коробки, просто делайте что-то в цикле, хотя бы просто инкременируйте переменную.
import time
def main():
i = 0
while i < 1000000000:
i += 1
start = time.time()
main()
finish = time.time()
print(finish-start)
Каналы и мьютексы МЕДЛЕННЫЕ. Добавление синхронизации через мьютексы на production настолько снизило скорость работы, что лучшим решением стал запуск процесса под daemontools и его перезапуск в случае падения.
Я не могу понять смысл Go. Если мне нужен системный язык, я использую C/D/Rust. Если мне нужен язык с хорошей поддержкой параллелизма, то я использую Erlang или Haskell.
Опыт (тестовые результаты) показывает, что они быстрее и эффективнее pthread_t языка C и POSIX.
Я либо сражаюсь с ограниченной системой типов с кастами всего в interface{} либо занимаюсь копипастой кода который делает практически одно и то же для разных типов.
Я вот пытаюсь понять,
как язык, в котором надо делать такие манипуляции может стать новой Java.
Ну и как? ;-)
А почему и как (?!) компилируемый в машинный код язык может стать «новой Java», которая требует интерпретации байт-кода в JVM?
В том-то и дело, что там не нужно делать такие манипуляции. Если человек все кастит в interface{}, значит он пытается перенести абсолютно чужие и крепко засевшие в голове паттерны туда, где они не нужны. Это печально, таких надо отсеивать на первом же собеседовании :)
а я о шаблонах и паттернах которые человек не хочет или не может пересмотреть по мере того, как он пытается освоить новый язык
И мой поинт в том, что когда человек не способен избавится от одного майндсета, навязанного одним языком, и посмотреть, как же можно подходит к проблеме иначе с другим инструментом — то это проблема этого человека, а не инструмента.
Высоконагруженный производительный софт и на С пишут
параметрический полиморфизм в том или ином виде есть в подавляющем большинстве современных статических языков
Можно честно признаваться в том, что ты привык к чему-то, или больше душа лежит — но нести откровенную чушь, выставляя это «минусами языка» уж явно не стоит.
If you’re not interested in my opinion, or are ending up here via some Go news aggregator or something and want to show me the error of my ways, you probably needn’t bother.
Да на всем пишут. Вопрос — какой ценой.
Я правильно понял?
Вот именно что, я спрашиваю как изготавливаются параметризированные контейнеры, а вы мне в ответ о шаблонах и паттернах которые человек не хочет или не может пересмотреть по мере того, как он пытается освоить новый язык.
Мне интересно как живётся без дженериков.
И мой вопрос — как часто вы пишете свои типизированные контейнеры? Можно в % от основного кода, или сколько раз в день, или сколько типизированных контейнеров вы написали в прошлом месяце?
standardized complex types
smaller language/compiler (if there aren’t many generic types)
language constructs can be optimized for these types
the code is more concrete (because users can build less abstractions)
each generic type adds complication to compiler
each generic type makes the language more complicated
the generic types must perform well in lots of cases
the language is less flexible (because users can build less abstractions)
и одна из обязанностей любого программиста — уметь правильно оценивать и выбирать инструменты. Быть не просто кодером, который только может клепать типизированные контейнеры и помнит все виды алгоритмов наизусть, а архитектором, понимающем возможности, недостатки и компромиссы технологий и подходов.
Преимущество сомнительное, в С++ при необходимости оптимизации просто определяют специализацию шаблона.
Если человек все кастит в interface{}, значит он пытается перенести абсолютно чужие и крепко засевшие в голове паттерны туда, где они не нужны.
Вы так и не ответили на вопрос
Пожалуйста, каков тогда «правильный» способ это сделать в Go?
Если человек все кастит в interface{}, значит он пытается перенести абсолютно чужие и крепко засевшие в голове паттерны туда, где они не нужны.
Да что ж там разбираться — храните interface{}, как в golang.org/pkg/container/list.
Таки в каких случаях пихать можно, а в каких – чужие паттерны?
На каждую комбинацию «тип элемента» + «вид сортировки» требуется повторять по 9 строчек однотипного кода.
Конкретная проблема — реализация типизированных контейнеров
Так как контейнер-то сделать?
Вот в этом, вероятно, и проблема.
Ad-hoc polymorphism что ли? Не ново. При определённой широте взглядов можно сюда хоть duck typing из питона или плюсовых шаблонов, хоть всякие ML'ные семейства систем типов приписать.
interface{} вообще мало кто из критиков (и не только) понимает.append всегда создаёт новый слайс. Но важно помнить, что часть одного слайса может быть так же частью другого. Если что есть copy. Да эта тема довольно проста и хорошо освещена, по крайней мере в англоязычном мире и не нужно хорошо знать язык, чтобы до неё дойти. Чувак просто не разобрался. Вот и всё.Я либо сражаюсь с ограниченной системой типов с кастами всего в interface{} либо занимаюсь копипастой кода который делает практически одно и то же для разных типов.Такое бывает у программистов, пришедших с других языков, когда они сражаются с языком, пытаясь насадить свои привычные паттерны и подходы к новому языку. Но, как правило, это не длится, даже в самом упоротом случае, больше двух недель. Если же у автора это продолжалось и вправду год, то всё *очень* печально.
Каналы и мьютексы МЕДЛЕННЫЕ. Добавление синхронизации через мьютексы на production настолько снизило скорость работы, что лучшим решением стал запуск процесса под daemontools и его перезапуск в случае падения.Разумеется, когда каждый может написать за минуту бенчмарк и посмотреть реальную производительность мьютексов и каналов, цифры в посте отсутствуют, как класс. Расчет на то, что читатель все примет на веру и скажет — «да, действительно, раз даже капсом написано, то и вправду медленные».
Строго говоря, утилита для анализа покрытия кода в Go — это хак.
Пользователи go хором говоря не пользоваться get, но при этом ничего не делают, чтобы пометить ее как неудачную реализацию и сделать официальную замену.
Эта реализация замаскирует паузы сборщика мусора, замедление связанное с гонками выделения ресурсов и другие интересные вещи, если они случаются не слишком часто.
многие проверки, которые обычно делает компилятор просто пропускаются — они реализованы в go vet.
В Go несколько уникальный подход — есть структуры и интерфейсы, первые определяют данные, вторые — поведение.
Я правильно понимаю, что для каждого отдельного случая перекладывания данных из одного Map в другой я должен реализовать свой собственный метод?
for key, value := range map1 {
map2[key] = value
}
Такое бывает у программистов, пришедших с других языков, когда они сражаются с языком, пытаясь насадить свои привычные паттерны и подходы к новому языку. Но, как правило, это не длится, даже в самом упоротом случае, больше двух недель.Вы наверное еще не пробовали Rust, раз думаете, что двух недель хватит всем. :D
map[string]string
и
map[string]notstring
станут эквиваленты, что усложнит работу type switch в Go и вообще является плохим решением.
Перевод: Один год с Go