Это как-то делает то, что в Go становится сложно? Еще раз, разговоров о том, что в Go очень просто и удобно писать конкурентный код (горутины, каналы, контекст).
напомню что разговор был не про «короче», а про «просто». Я сказал, что очень просто запустить горутину (к этому прицепились сразу) и управлять ее, и взаимодействовать (каналы).
Дело в том, что эту ситуацию описывают как проблему рантайма или планировщика, что не так (даже если планировщик будет уметь приоритеты, все равно может быть все горутины с одинаковым приоритетом).
Конечно же такая ситуация может быть и часто, но еще раз — все потоки выполняются и не заблокированы. Если такая ситуация появилась — нужно либо оптимизировать алгоритм либо скейлить.
Выше было сказано, что код «ставит колом целиком поток», а это не так (все потоки выполняются). Значит неправильно понимают (может я непонятно выразился с «воспринимают»). Но сути дела это не меняет.
Смотря как вы будете формировать отчет — вам нужно будет его откуда-то читать, да? Построчно? Вот вам уже и сисколы, уже будет переключение горутин.
Но давайте так, допустим каждая горутина просто должна спать 1 минуту (ну типа чисто в памяти что-то 1 минуту считаем, без сисколов). Сделав 9 запросов, девятый будет ждать. Только это не проблема языка или рантайма, с точки зрения рантайма все очень даже хорошо — все тредэ ранятся и нету заблокированных.
Ну да, тред работает, только остальные горутины остались в пролете. Бесконечный цикл скорее всего исключение, но вот долгое выполнение вполне реально может случиться. Пользователю то пофиг, тред твой тормознулся или занят непонятной херней, ему главное чтобы сайт не тормозил, а вместо этого получит 503.
Вы написали бредовый код и пытаетесь натянуть его на реальную картину — нет, так не работает.
Пишите код, который не будет выполнять непонятную херню.
Да я откуда знаю, может есть еще и другие способы. Тем не менее, это работает не так как написал qrKot. Это не плохо и не хорошо, это примерно также как и у других.
А как? Ваш пример был ошибочным, трэд там в состоянии Running и то что сказал qrKot подтвердилось вашим же примером.
Вы так говорите, как будто это уникальная фича go, да у всех асинхронных серверов так. Понятно что в старых языках типа Java остались синхронные апи для I/O, ну сам себе буратино что используешь их в асинхронном методе. Ну кстати не всегда и требуется переписывать на асинхрон, я как-то переписал консольную утилиту и она стала медленнее работать, накладных расходов потому что стало больше чем полезного кода.
Я не говорю про уникальность, это тут все любят сравнивать, я вам привел пример как сделано в Go. При этом асинхронный I/O это совсем другое (был как пример).
Вы уже уходите от темы, то есть вы согласны что «никакая горутина не может поставить колом целиком поток»?
Конечно же есть затраты на парковку goroutine и context switch (стэк, кстати, у каждой горутины свой и алоцируется при создании), но это ничтожно мало с, например, ожиданием I/O. Как уже говорили, Go хорошо подходит для Web.
Вот в Go, за счет того, что заблокированая горутина паркуется и не блокирует трэд, второй запрос у вас обработается быстрее, так как во время I/O первой горутины, будет выполняться вторая.
А чего вы хотите увидеть? Я пока вас не понимаю.
В Go кооперативный (почти) планировщик, планирует goroutine по доступным тредам — у вас 8 goroutine не блокируются, не делают системных вызовов, просто инкрементят счетчик, всегда в running состоянии.
Только вот в реально мире такого не будет. Вот добавьте всего одну строчку (fmt.Println(t) в цикле функции test) и у вас совсем другой результат.
func main() {
for i := 1; i < 100500; i++ {
go test(0)
}
time.Sleep(1)
go fmt.Println("main 1")
fmt.Println("main 2")
}
func test(t int) {
fmt.Println("start")
for true {
t = t + 1
fmt.Println(t)
}
fmt.Println("stop")
}
Не знаю что там в C#, говорю как удобно в Go (опять же начались примеры в стиле "а вот в X языке точно такая же фича"). Ну и даже краткость записи — уже ведь лучше, да? Ведь тут все хейтят Go с if err != nil. В вашем примере мне не понятно, что такое Task, это ваш класс или со стандартной библиотеки?
Можно сделать все что угодно, только вот в Go это часть стандартной библиотеки (как и пакеты context и sync для управления goroutine).
В сумме все это очень упрощает написания конкурентного кода.
Связка tokio+futures-await так же удобны в использование как горутины.
Прям вот точно также удобны?
Удобство goroutine в том, что их просто стартануть (go перед любой функцией/методом) и то, что есть каналы для их взаимодействия. В Rust тоже есть каналы?
Я уже почти 4 года программирую на Go: мне не нужно генерировать шаблонный, мне не нужны дженерики, уже давно есть удобный пакетный менеджер (сейчас еще модули завезли), компилятор очень сильно помогает (зависит с чем сравнивать, да?). В основном я пишу/писал web сервисы (нагрузка от 30к до 400к RPS), стрим процессинг с Kafka, тулзы для Kubernetes, etc.
Мне нравится Go, мне нравится вот это if err != nil, после Java я совсем по другому начал относится с ошибкам.
И я совсем не понимаю, почему пользователи Хабра в каждом посте про Go начинают бегать туда-сюда с криками насколько Go ужасный язык, при этом 80% из них на Go не программируют. Начинают сравнивать отдельные фичи Go с фичами других языков — а вот в Х яызке это лучше, а вот в Y языке другое лучше: — Но я использую Go, мне нравится X фича и для моих задач Go подходит идеально. Тем более у нас есть опыт на Go. — Ты не понял, Go говно, там if err != nil, вот тебе Rust/C++/Haskell/JavaScript там еще лучше. Монад ведь нету в Go? Воот, ерунда ваш Go.
В каждом посте овер 200 комментов, больше половины из которых вот такие бессмысленные срачи.
В примере выше вывод типа происходит у аргумента замыкания. В примере с функцией call, так же вывод типа происходит у аргумента замыкания за счёт того, что в сигнатуре функции явно указан тип аргумента замыкания.
Вы же указали тип функции и тип аргумента функции, вот же он &Fn(String). Функция example_fn ждет первым аргументом String. Если там не String — то ошибка компиляции.
Ваш изначальный пример — это свойства анонимных функций, а не вывод типа анонимной функции из сигнатуры.
Сейчас я еще больше запутался, чем тогда это отличается от Go?
```go
func main() {
example_fn := func(x string) string { return x }
print(example_fn(«hello»))
example_fn2 := func(x int) int { return x }
print(example_fn2(10))
}
```
Как раз в первом варианте (тот что с callback), там выводится тип анонимной функции по первому использованию и после этого выведенный тип удовлетворяет сигнатуру функции **call**.
Можете кинуть ссылку на документацию по этому?
UPD: как раз в Go тип переменной вывелся из присваиваемого значения.
Тип анонимных функций определяется при первом использовании. Потому, если я все правильно понял.
Вот у вас функция: println!("{}", call(10, 10, |a, b| a + b));, а вот тут первое использование — c(a, b). a и b имеют тип i64, потому у этой анонимной функции будет тип Fn(i64, i64) -> i64, а не потому что в сигнатуре where F: Fn(i64, i64) -> i64.
let example_fn = |a| a;
println!("{}", example_fn(String::from("Yo"))) // вот тут уже будет тип Fn(String) -> String
let example_fn2 = |a| a;
println!("{}", example_fn(2)) // вот тут уже будет тип Fn(i64) -> i64
То есть вы мне предлагаете сделать что-то (как virtualenv или собрать python в бинарник) вместо того, чтобы ничего этого не делать и называете это преимуществом?
Отсутствие зависимостей всегда лучше их наличия и ansible тут не панацея.
Тулзе А нужна 2.2 версия, а тулзе Б 3.1. Блин, надо virtualenv настраивать?
Потом pip или yum — чем мы там python зависимости ставим? А уже везде дефолтная версия python3? Ахх, тут на 100 серверах yum'ом установили, а на другой сотне pip'ом.
Блин, ansible yum модуль поставил библитеку libA-2.3.0 хотя я явно же написал поставить libA-1.9.0 (ох state: latest игнорит версию в названии пакет).
Блин, OS команда не дает нам root (не доверяют), а мне надо бы новую зависимость установить, опять virtualenv настраивать, а как же с C зависимостями?
И так далее.
Преимущество есть и оно большое (может быть конечно не "невообразимое").
Да нет, как раз вы добавляли условий, потому что вас не устраивали ответы и вы пытались подогнать все под свою позицию. При этом вы будете игнорировать безопасность, высокодоступность, чтобы только подогнать все под ваше решение.
А это уже зона ответственности PaaS-платформы, которой вы пользуетесь.
Я ее разрабатываю.
Но не все пользуются облачными платформами, не у всех 1 rps нагрузка и так далее. Вы тут подобрали специальные условия и представляете свое решение как единственно правильное учитывая только ваши условия.
Вы сейчас это серьезно?
Не надо сейчас придумывать, что там принято в Go.
Вот эта ваша самоуверенность удивляет — проблемы могут быть везде, начиная от железа, проблем сетью и до того, что админ или вы случайно кильнете ваш сервис. Но у вас «В дотнете риск существует только при обновлении.».
Магия, не иначе.