LINUX.ORG.RU

Golang HTTP Middleware

 , ,


0

3

Пошаговая инструкция понимания Golang HTTP Middleware.

Вариант №1:

  1. Надо представить сервер как процесс с STDIN/STDOUT.
  2. Надо понять что STDIN/STDOUT обслуживаются объектами созданными по лекалу интерфейсов. И названными r/w. Ну и порядок перевернут w,r в сигнатуре.
  3. Вот ту ключевое - обрабатывается ОДНОЙ ФУНКЦИЕЙ которую вызывают. ТОЧКА.
  4. А дальше расширить понимание, что Эту функцию можно вызывать каскадом.
  5. И последнее уже переходное, то MiddleWare КОНСТРУИРУЕТ функцию. По этому каждый этап MiddleWare Возвращает валидный ServerHTTP! Который либо Пишет сам. Либо завет чужой хендлер по замыканию.

Вариант №2:

  1. Представить HTTP сервер как UNIX Процесс с STDIN/STDOUT.
  2. Понять что STDIN и STDOUT обрабатываются через инстансы созданные по «чертежам интерфейсов». STDIN - Resquest, STDOUT - Response. (STDIN=Request=Read):(STDOUT=Response=Write).
  3. Запрос обрабатывается одной функцией. Точка.
  4. Расширить понимание, функцию можно вызывать каскадом.
  5. Middleware не функция для вызова, это функция которая ВОЗВРАЩАЕТ функцию для Вызова.

🎆 Отливаем в бронзе, лаконичная формула от Qwen:

Middleware в Go — это не хук. Это фабрика функций.

Она принимает Handler, возвращает Handler, а внутри — через замыкание — решает, когда и как вызвать следующий.

🎆 От ChatGPT:

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

🎆 От DeepSeek:

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

🎆 От Grok:

Middleware в Go — это фабрика функций. Она принимает http.Handler, возвращает http.Handler, а внутри через замыкание решает, когда и как вызвать следующий (или прервать цепочку). Это не «добавление хука». Это оборачивание одного обработчика в другой, создающее конвейер (pipeline).

📀 P.S.

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

type HandlerFunc func(http.ResponseWriter, *http.Request)

func (f HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    f(w, r)
}

По этому функцию можно приводить к типу этого интефейса Hanlder. Изюминка заключается в том, что http.HandlerFunc(hello) - это не вызов метода. Это приведение к типу (type conversion) HandlerFunc.

🎆 Полировка от DeepSeek:

Благодаря http.HandlerFunc любую функцию с сигнатурой (ResponseWriter, *Request) можно привести к типу http.Handler, что делает оборачивание элегантным и типобезопасным.

🎆 Полировка от Qwen:

http.HandlerFunc(f) — это статический адаптер, который превращает функцию в объект, реализующий интерфейс, через навешивание метода на тип-функцию.

🎆 Полировка от ChatGPT:

В выражении http.HandlerFunc(hello) происходит приведение обычной функции к функциональному типу HandlerFunc, что позволяет этому значению получить метод ServeHTTP и тем самым реализовать интерфейс http.Handler.

🎆 Полировка от Grok:

http.HandlerFunc — статический адаптер, который позволяет любой функции с правильной сигнатурой стать http.Handler и участвовать в этой цепочке.

Middleware в Go — это фабрика функций.

Она принимает http.Handler, возвращает http.Handler, а внутри через замыкание конструирует новый ServeHTTP, который решает, когда вызвать следующий слой.

Это не «добавление хука», а оборачивание одного обработчика в другой, создающее гибкий конвейер (pipeline).

📀📀 P.P.S.

Что еще важно, так как в итоге ServeHTTP метод который вызывается для обработки запроса представляет собой наслоение замыканий «кольцами», то из любого кольца можно принят решение о немедленном выходе, ни погружаясь дальше. Вот так вот изящно формируется в Golang единственная функция обработчик, которая в себе имеет сколь хватит памяти уровней, и к каждый уровень это Middleware или отдельный метод. Метод либо прерывающий цепочку и отвечающий в http.Response, или вызывающий следующий метод, переходя в новый слой.

🎆 Полировка от Qwen:

Middleware в Go — это управляемый конвейер с возможностью аварийной остановки. Каждый слой обладает полным правом вето: он может обработать запрос самостоятельно и завершить цепочку, не беспокоя следующие уровни.

🎆 Полировка от DeepSeek:

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

🎆 Полировка от ChatGPT:

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

В Go HTTP middleware формирует один итоговый обработчик через композицию замыканий. Каждый слой получает управление и решает: вызвать следующий обработчик или завершить обработку, сформировав ответ. Таким образом, вся цепочка — это одна функция с контролируемым потоком выполнения.

🎆 Полировка от Grok:

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

🐳 Итоговая формула (собранная из цитат) от DeepSeek:

Middleware в Go — это не цепочка вызовов и не система перехвата событий. Это фабрика, которая конструирует единый метод ServeHTTP как 🪆 матрёшку из замыканий.



Последнее исправление: lbvf50txt (всего исправлений: 11)
Ответ на: комментарий от paddlewan

Напротив, это тема уровня trainee. Потому что все сводится, в сущности, к пониманию замыканий, как вам ИИшечка и подсказала.

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

Смысл статьи еще до LLM - это указание анкерных точек для понимания, смещение фокуса с обработчика, на фабрику. Вся критика идет на уровне Junior/newMiddle - цепляние к синтаксису и попытка обесценить, для возвышения.

Вот я вам предлагаю разберите механизм обработки HTTP запроса полней, приведите строение сервера, сущность мультиплексора в пакете net/http. Тогда это будет разговора на уровне Middle+/Senior. Разговор про архитектуру.

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

Ваш выход. Прошу. Давайте продолжим про архитектуру обработки запроса. Примеры рассуждения я многократно продемонстрировал в описании приведение функций к инстансам через type conversion, и так далее по общей архитектуре решения.

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от paddlewan

Уважаемый, а зачем этот пафос «подумайте почему так» в одном из базовых примеров использования defer?

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

Постоянна попытка диктовать сверху, уличать, унижать. Можно спокойно сказать, еще defer используется как инструмент для восстановления. Нет, надо «подумайте почему так». У-у-у-у-у-у «эксперт педагог» в комнате.

lbvf50txt
() автор топика
Ответ на: комментарий от monk

Кто сказал про сетевые?

Golang создавался под конкретные задачи, конкретной корпорации. Это язык для обработки большого количества HTTP запросов. Это является целью языка.

Так претензии про наличие GC имеют смысл только в контексте реального времени.

На форумах претензии к Golang без контекста. Вот как пример вашего высказывания.

«нормальный программист уже 30 лет может писать»

Стало быть, тот кто не знает Lisp, он уже не «нормальный программист». Оказывается не сложность решенной задачи определяет разработчика, а инструмент.

И оказывается не умение писать в определенных парадигмах определяет качество кода. А инструмент на которых эти парадигмы реализованы.

  • Lisp - респект, «настоящий пацан».
  • JS, Go - «слабак, не настоящий».

Что это такое? Это типичная форумная критика Go.

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от lbvf50txt

попытки обесценить проведенную мной работу

«Мной»! Бггг.

На данный момент в треде 54 камента, слово «обесценивание» в разных формах встречается 11 раз.

Пора тебе в ретрит, хватит находиться в токсичной среде.

thesis ★★★★★
()
Ответ на: комментарий от lbvf50txt

Стало быть, тот кто не знает Lisp, он уже не «нормальный программист».

Всегда так было.

ugoday ★★★★★
()
Ответ на: комментарий от monk

Вот я вам просто объясню смысл Go. Весь смысл языка Go, в реализации Goroutine. Обратите внимание на игру Go язык, Go игра, Google, Gorounite.

Что такое Горутины и зачем они нужны?

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

Если раньше обработка HTTP разделялась на нескольоко процессов HTTP сервер, потом запуск интерпретатора, потом CGI и передавание инфы черзе потоки. То в Go - все упокавали в один процесс. Это на минуточку 2009 года, когда Perl еще во всю использовался как и Apache.

Едем дальше. В Golang реализовали свой собственный планировщик. И назвали эту тему так G/P/M. G - горутина, P виртуальный процееор в внутри рантайма Go, М - это поток в Машине, он же Thread.

Что получили, что при IO-bound задачах, когда поток зависает в ожидании чего-то, можно отложить Горутину с подвисшим потоком, и взять на исполнение другу горутину, отклеив P виртуальный процессор от потока.

Другими словами Go решает ту же задачу, которую решали на мейнфреймах в 1960ых годах, когда обратили внимания, что большинство задач ожиают отклика от пользователя, а CPU простаивает. Тогда создали Preemptive Multitasking. Тут то же самое, но в рамках процесса. Пока куча Горутин ждет отклика по сети, другие выполняются.

По этому смысл Go не в синтаксисе, а в механизме планировщика, который снимает с разработчика кучу головников. И позволяет оптимально расходовать CPU время, при IO-bound задачах.

lbvf50txt
() автор топика
Ответ на: комментарий от lbvf50txt

Golang

Извини, слух режет. :)

Is the language called Go or Golang?

The language is called Go. The “golang” moniker arose because the web site was originally golang.org. (There was no .dev domain then.) Many use the golang name, though, and it is handy as a label. For instance, the social media tag for the language is “#golang”. The language’s name is just plain Go, regardless.


https://go.dev/doc/faq#go_or_golang

urxvt ★★★★★
()
Ответ на: комментарий от lbvf50txt

Вот я вам предлагаю разберите механизм обработки HTTP запроса полней

А что там разбирать? Открой (раз уж перешел на «ты») код стандартной библиотеки и почитай просто, никто не прячет же.

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

paddlewan
()
Ответ на: комментарий от lbvf50txt

Уважаемый, а зачем этот пафос «подумайте почему так» в одном из базовых примеров использования defer?

Потому что ты сказал выше, что defer - это чтоб ресурсы высвобождать. Это неправильно. Я процитировал ошибочный тезис и предложил подумать, почему он неверен, и даже пример привел.

У-у-у-у-у-у «эксперт педагог» в комнате.

Бро, я на прошлой неделе провел n собеседований на ведущего разработчика на Go. Да, кой-чего смыслю в языке. И да, бываю даже педагогом для менее опытных коллег. Ты читай, что тебе по существу пишут, не ищи кругом врагов, они сами тебя найдут :)

paddlewan
()
Последнее исправление: paddlewan (всего исправлений: 1)
Ответ на: комментарий от paddlewan

Бро, я на прошлой неделе провел 10 собеседований на ведущего разработчика на Go. Да, кой-чего смыслю в языке.

Слушай, Вася, не надо трясти своими медальками. Сколько лет ты обработал и кого и как ты собеседвал и какую вывеску вы себе повесели на ваш отдел.

Ты пришел «блатовать» тебе предложили побеседовать о Архитектуре net/http в Go. После чего ты технично слился со словами: «Иди читай код» и начал опять обесценивать чужой труд и чужие задачи.

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от paddlewan

А что там разбирать? Открой (раз уж перешел на «ты») код стандартной библиотеки и почитай просто, никто не прячет же.

Понятно.

lbvf50txt
() автор топика
Ответ на: комментарий от lbvf50txt

Ох, нет, бро, с тобой мы беседовать больше ни о чем не будем, потому что ты хамишь :) :) :)

Давай дальше развлекайся сам с собой тут :)

paddlewan
()
Ответ на: комментарий от kaldeon

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

Ручная статика всегда лучше там, где она применима. Поэтому в Common Lisp есть declare type, а в Racket есть Typed Racket.

Но применима она не везде, поэтому в C есть *void, а в Go есть interface{}.

monk ★★★★★
()
Ответ на: комментарий от lbvf50txt

По этому смысл Go не в синтаксисе, а в механизме планировщика, который снимает с разработчика кучу головников. И позволяет оптимально расходовать CPU время, при IO-bound задачах.

Erlang придумали раньше. И даже NodeJS в том же 2009. И в Racket зелёные потоки примерно в том же году были.

Смысл Go именно в том, что он был удобен для Google. И кастрировали его из тех же соображений, что и Java. Чтобы разброс времени решения задачи у разных программистов был не 50 раз как на C++, а 3-4 раза.

monk ★★★★★
()
Ответ на: комментарий от lbvf50txt

Стало быть, тот кто не знает Lisp, он уже не «нормальный программист». Оказывается не сложность решенной задачи определяет разработчика, а инструмент.

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

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

monk ★★★★★
()
Ответ на: комментарий от lbvf50txt

Стаж не тождественен классу. Зачем вы трясете этой медалькой?

Ну ты же бесконтактным вин-чунем зачем-то тряс в теме про TCP.

slackwarrior ★★★★★
()
Ответ на: комментарий от urxvt

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

В Go занимаются оптимизацией Scheduler и GC. Когда начинаешь читать про эти вопросы, то бесконечные минорные версии Go начинают иметь свой смысл. Точно я не помню, но что запомнил ключевые - механизмы меняют серьезно. А так как фактический смысл Go - это оптимизация распихивания Горутин по «Ядрам», то это самые важные обновления.

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

Синтаксис в принципе сильно вторичен. Даже это Middleware решение - не особо нужно, можно не заворачиваясь слепить один большой объект с одним методом и отдать его мультиплексору. Работать будет.

Ну так да, красиво, мне формат «Композиции через Замыкание» понравился как идея. Но опять же, такие изыски абсолютно не критичны. Если выстроить по порядку набор методов с if/else - ничего не изменится.

P.S.

Всё изящество Архитектуры Go в том, что он не навязывает какой-то сверх изысканных синтаксис. Хочешь писать просто - пиши. Есть один Объект с методом в котором STDOUT/STDIN. И всё: тут прочитал из Request, туда байты залил в Response. Заработало. А дальше твое дело.

При желании можно «жонглировать» и «джигитовать», запускать замыкания в defer меняя named return. Честно говоря, я этого насмотрелся в RubyOnRails, развернулся и ушел в Go. Этап джигитовки и code golf я прошел с Ruby, вот там верх изящества всё возможные способы деления массива, удельный вес строки кода огромный. А в RubyOnRails код не возможно читать без отладчика и буквально не работают vim tags - есть масса вхождений определений, переопределий, дозаливок-замешниваний.

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

По этому меня синтаксическая эквилибристика не впечатляет, на оборот, она у меня вызывает приступ скуки. Наигрался. Ну и потом, разбирать даже свои собственные шедевры занятие то еще. По этому, в итоге, свободу Ruby ограничивают добавляя линтеры с жесткими правилами, например, требуется вместо reduce писать with_object.

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 8)
Ответ на: комментарий от lbvf50txt

Всё изящество Архитектуры Go в том, что он не навязывает какой-то сверх изысканных синтаксис.

Это путь Java. При наличии нормального IDE, который генерирует и рефакторит весь этот текстовый шум, даже нормально. Без IDE что на Java что на Go приходится писать слишком много букв. COBOL наших дней.

monk ★★★★★
()
Ответ на: комментарий от lbvf50txt

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

Тю. Самое главное в языке это его синтаксис, объем этого самого синтаксиса (см. С++), инфраструктура, стандартная библиотека и т. д. Короутины по ядрам пускать умеют чуть менее чем все. Го тут был далеко не первым. Вон даже в Яву завезли их из коробки.

Синтаксис в принципе сильно вторичен.

Это твое утверждение противоречит подходу Пайка и ко (см. те же дженерики, скорость компиляции, автоформатировани и т. д.).

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

на Го и можно писать в Имаксе

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

ugoday ★★★★★
()
Ответ на: комментарий от lbvf50txt

и думает о коММанде

у вас узбекский (не в обиду узбекам) LLM?

borisych ★★★★★
()
Ответ на: комментарий от urxvt

Короутины по ядрам пускать умеют чуть менее чем все. Го тут был далеко не первым. Вон даже в Яву завезли их из коробки.

Не путайте две сущности OS Thread и Goroutine. Обе сущности для упрощения называют потоками, чтоб не читать 3х часовую лекцию и не проводить еще 2х часовую практику. ОS Thread - это часть услуг OS и ее умеют все языки, а вот Goroutine это именно разработка команды Go и она революционна для 2009 года.

Goroutine - имеет примерно такое же отноешие к OS Thread, как OS Thread имеет к OS Process. Когда Тред зависает ожидая IO операцию, или Goroutine зависает ожидая netpoll, работа Go програмы продолжается, потому что горутины склеены с тредами через прослойку вирутальный процесессоров. И вся эта схема называется M:N Multitasking, и еще точней G/P/M где M - Machine Thread.

Если заблокировался OS Thread - тогда Go Runtime просто переклеит вируальный процессор на другой OS Thread.

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

Вывод:

Горутина - это не Тред. Горутина - это сущность которая может переключаться между Тредами. И это и есть главное в Golang.

Суть Golang которая сделал его по настоящему привлекательным и отличающимся от множества других языков в 2009 году был как раз механизм позволяющий уменьшить простаивание процессора при IO-bound задачах. Когда у вас ни Thread не замораживается так как алгортим ждет ответа от netpoll, и алгоритм не зависает так как Thread приостановлен для получения IO ответа.

P.S.

Извините, для меня Go - это настольная игра с 1000 летней историей, о которой мы беседовали в университете гуляя по аллеям. А язык программирования Golang, где его сокращенное имя является красивой игрой слов Go, Google, Go.

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от urxvt

Это твое утверждение противоречит подходу Пайка и ко (см. те же дженерики, скорость компиляции, автоформатировани и т. д.).

Вы контекст то беседы отслеживайте дальше чем на 1 сообщение. Мы беседовали с вами о том, что Golang меняется - к нему добавляется множество синтаксических фич.

По этому я говорю не вообще о синтаксисе Go в целом, а о синтаксических добавлениях которые вторичны. Самый классический Go первых версий имеет достаточно хороший синтаксис, чтоб воспользоваться его основным преимуществом: G/P/M моделью M:N многозадачности.

Дженерики, которые лично мне даром не нужны, это как электрические стеклоподъемники в машине - фича которая ничего не меняет, я и ручкой окно открою. Главное в машине - двигатель, ходовая, надежность КПП, кузов. Ну и так далее. Идею вы поняли.

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 3)
Ответ на: комментарий от beastie

Время выполнения запроса + прямая последовательность выполнения

vs

Время выполнения метода от текущей позиции + отложенное выполнение

Что действительно лучше?

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

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

kaldeon ★☆
()
Ответ на: комментарий от lbvf50txt

https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part2.html

Хороший цикл статей про многозадачность в Go, от William Kennedy. William Kennedy автор книги Go in Action - рекомендую. Читал. Хорошо описывает типы в Golang и переходы между ресиверами на указатель и на значение.

Once again, Go adjusts the value to comply with the method’s receiver to support the call.

В месте с книгой Jon Bodner «Learning Go» - получается комбо. Две книги друг друга дополняют.

lbvf50txt
() автор топика
Ответ на: комментарий от kaldeon

Проблемы начинаются там, где между start и end не одна строчка, а какая-нибудь «Война и Мир» с множеством точек выхода и десятком авторов, как это обычно бывает в реальной жизни. Вариант с defer делает подобный замер времени локальным, а не размазанным по всей функции. В туториалах, это конечно скорее всего не так важно. А совсем серьёзные дяди используют что-то вроде opentelemetry, а не такие костыли. ¯\_(ツ)_/¯

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от lbvf50txt

Не путайте две сущности OS Thread и Goroutine. Обе сущности для упрощения называют потоками, чтоб не читать 3х часовую лекцию и не проводить еще 2х часовую практику. ОS Thread - это часть услуг OS и ее умеют все языки, а вот Goroutine это именно разработка команды Go и она революционна для 2009 года.

С чего тебе показалось, что я их путаю? CSP Хоар ещё в 80-х придумал. Erlang таких же бородатых времен. Почти во всех языках подобное было и есть в качестве библиотек, просто Го встроил это в язык (далеко не первым, см. Ерланг, Лимбо и т. д.).

А язык программирования Golang, где его сокращенное имя является красивой игрой слов Go, Google, Go.

Только в реальности это не так. О чём и говорят авторы. ;)

urxvt ★★★★★
()
Ответ на: комментарий от beastie

Тут тоже можно предложить другое решение:

func(g func()) {
    start := 0
    g()
    end := 42
    fmt.Println(end - start)
}(func() {
    // war and peace
})

На практике я такие чудеса ещё не писал. Выглядит странновато.

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

Если же использовать мой пример, то при панике строчки в логе не будет. Это тоже вводит в заблуждение, но в отличие от 0 мы сможем отследить логику программы по коду: если control flow не сходится (не приводит нас к обходу логирования), вывод один - паника.

kaldeon ★☆
()
Последнее исправление: kaldeon (всего исправлений: 5)
Ответ на: комментарий от lbvf50txt

Суть Golang которая сделал его по настоящему привлекательным и отличающимся от множества других языков в 2009 году был как раз механизм позволяющий уменьшить простаивание процессора при IO-bound задачах. Когда у вас ни Thread не замораживается так как алгортим ждет ответа от netpoll, и алгоритм не зависает так как Thread приостановлен для получения IO ответа.

Повторюсь, coroutine, green thread, another-name были доступными почти во всех языках. В той же Scala акторы появились ещё до Go.

urxvt ★★★★★
()
Ответ на: комментарий от lbvf50txt

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

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

С чего тебе показалось, что я их путаю? CSP Хоар ещё в 80-х придумал. Erlang таких же бородатых времен. Почти во всех языках подобное было и есть в качестве библиотек, просто Го встроил это в язык (далеко не первым, см. Ерланг, Лимбо и т. д.).

Мне так показалось потому, что вы говорите о «почти всех языках». А приводите одни из самых экзотических, о которых не каждый студент МехМата знает, даже если он энтузиаст программирования.

Почти во всех языках (за исключением Perl, Ruby, Python, JS) была работа OS Threads. Вот это было. JS в 2009 году был, как мне кажется, однопоточным, но асинхронным из-за EventLoop.

lbvf50txt
() автор топика
Ответ на: комментарий от kaldeon

Я не знаю, к чему ты тут про паники вспоминаешь. Их и так за километр видно. И ловить их можно точно так же. Никто несколько деферов на функцию не запрещал.

А по поводу подобных замеров времени – это скорее временный отладочный код. И гораздо проще влепить в начале функции пару строк (что бы потом их опять удалить), чем бегать по всему коду и расставлять start/end.

Это как бы мои пять копеек. Я не полиция, ничего не запрещаю. ;) Просто делюсь опытом.

И как уже говорил – это просто вспомогательный костыль. Если по хорошему мерять надо, то это pprof / OpenTelemtery и подобное.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 2)
Ответ на: комментарий от urxvt

Так я и говорю, что большинство Го любят не за гороутины.

Мы уже выходим на 3й круг повторений. Что там любит «большинство» - вопрос спорный. Есть фактический механизм который отличал Golang от популярных языков начала 2010ых - G/P/M многозадачность.

Этот механизм позволял не приостанавливать обработку множества HTTP запросов сортируя ожидающие и уже получившие ответ. Это факт технического плана - механизм находился в «шаговой доступности», по этому им пользовались.

То что подобную задачу можно решить не только на Go - я не спорю.

lbvf50txt
() автор топика
Ответ на: комментарий от kaldeon

Формально он прав, CSP можно сделать в любом языке через библиотеку. Так было, например, в Plan 9.

Не спорю. Конечно можно. Ученые математики еще в 60ых годах полностью «исследовали функцию программирования на экстремумы». Диапазон всех возможных решений был просчитан математически, появились разные теоремы о «вычислимости» и так далее.

Все возможности архитектуры компьютера где есть адресное пространство и некий вычислитель - были проанализированы точно так-же как 11 классник анализирует «двухэтажную» формулу на перегибы через производные.

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

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от urxvt

Много, много лет назад, я постоянно читал документацию к PHP5. Она еще была в форме справки Windows. И вот там была разделе «Как писать музыку на PHP» - и объяснялось, что PHP для написания музыки не подходит.

Точно также Go - никогда не был языком «общего назначения». Что бы там, кто бы там не говорил. Это язык созданный под абсолютно конкретную задачу, в абсолютно конкретном месте.

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

Каждое архитектурное решение, вся структура стандартной библиотеки - говорит об одном - упакуй все сервера (TCP/HTTP/Multiplexer) в один OS Process, пусть многозадачность будет через Goroutines. Экономь на всем, делай так чтоб было быстро.

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

lbvf50txt
() автор топика
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.