HTTP-сервер на net/http: регистрация обработчиков и формирование ответа
Содержание курса
http.ListenAndServe: блокирующий запуск, обработка ошибки и рабочий цикл с двумя терминалами
Когда маршрутизатор готов, его нужно передать серверу:
if err := http.ListenAndServe(":8080", mux); err != nil {
log.Fatal(err)
}
http.ListenAndServe принимает адрес для прослушивания и http.Handler — интерфейс, который реализует *http.ServeMux. Функция открывает TCP-сокет на порту 8080 и входит в бесконечный цикл приёма соединений. Она блокирует текущую горутину — то есть строки после неё в нормальном режиме работы никогда не выполнятся.
Именно поэтому нельзя просто написать http.ListenAndServe(...) и продолжать код ниже: сервер занял поток и ждёт запросов.
Что происходит на практике:
- Запускаете программу в первом терминале — он «зависает» (это нормально, сервер работает).
- Открываете второй терминал и отправляете запрос:
# Linux / macOS
curl http://localhost:8080/hello
# Windows PowerShell
Invoke-WebRequest http://localhost:8080/hello
- Сервер обрабатывает запрос, первый терминал может показать логи, второй — ответ.
- Чтобы остановить сервер, нажимаете
Ctrl+Cв первом терминале.
Почему log.Fatal? ListenAndServe возвращает ошибку только в одном случае: что-то пошло не так при запуске или во время работы — например, порт уже занят другим процессом. Игнорировать эту ошибку нельзя: без неё вы не узнаете, что сервер вообще не стартовал. log.Fatal выводит сообщение и завершает программу с ненулевым кодом.
Типичная ошибка при занятом порте выглядит так:
2024/01/15 10:23:45 listen tcp :8080: bind: address already in use
Если написать http.ListenAndServe(":8080", mux) без проверки — программа завершится молча или продолжит выполнение с незапущенным сервером, и отлаживать это будет неудобно.
