Подтвердить что ты не робот

Есть ли концепция обратного вызова?

Я нашел много разговоров о том, что Node.js плохой из-за callback-ада, и Go хорош из-за его синхронной модели.

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

Итак, почему они сравнивают Go и Node.js в перспективе обратного вызова, как будто Go не может стать аддоном обратного вызова.

Или я неправильно понимаю смысл обратного вызова и анонимной функции в Go?

4b9b3361

Ответ 1

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

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

doSomething1(arg1, arg2, function() {
  doSomething2(arg1, arg2, function() {
    doSomething3(function() {
      // done
    });
  });
});
somethingElse();

doSomething1 может занять много времени (потому что ему нужно читать из сети, например), но ваша программа все равно может выполнить somethingElse в среднем времени. После выполнения doSomething1 вы хотите вызвать doSomething2 и doSomething3.

С другой стороны, основывается на концепции goroutines и каналов (google для "Коммуникации последовательных процессов", если вы хотите больше узнать об абстрактной концепции). Горотины очень дешевы (вы можете одновременно запустить несколько тысяч из них), и поэтому вы можете использовать их везде. Тот же код может выглядеть так: Go:

go func() {
  doSomething1(arg1, arg2)
  doSomething2(arg1, arg2)
  doSomething3()
  // done
}()
somethingElse()

В то время как node.js фокусируются на предоставлении только асинхронных API, Go обычно рекомендует вам писать только синхронные API (без обратных вызовов или каналов). Вызов doSomething1 заблокирует текущий goroutine, а doSomething2 будет выполнен только после завершения doSomething1. Но это не проблема в Go, поскольку обычно доступны другие goroutines, которые можно планировать для запуска в системном потоке. В этом случае somethingElse является частью другого goroutine и может выполняться тем же способом, что и в примере node.js.

Я лично предпочитаю код Go, так как его легче читать и рассуждать. Другим преимуществом Go является то, что он также хорошо работает с вычислительными тяжелыми задачами. Если вы начнете тяжелое вычисление в node.js, которому не нужно ждать сети вызовов файловой системы, это вычисление в основном блокирует цикл событий. Go scheduler, с другой стороны, сделает все возможное, чтобы отправить goroutines на несколько системных потоков, и ОС может запускать эти потоки параллельно, если ваш процессор поддерживает его.

Ответ 2

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

Итак, почему они сравнивают Golang и Node.js в перспективе обратного вызова, как будто Golang не может стать адским обратным вызовом.

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

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