Тип http.Server
Тип http.Server представляет собой HTTP-сервер,
который позволяет настраивать параметры обработки входящих
запросов. В структуре сервера можно задать адрес прослушивания,
обработчик запросов, таймауты и другие параметры. Основными
методами типа являются ListenAndServe для запуска
сервера, Shutdown для graceful остановки и
Close для немедленного закрытия.
Синтаксис
server := &http.Server{
Addr: ":8080",
Handler: nil,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
Для создания экземпляра сервера используется литерал структуры
с указанием необходимых полей. Поле Addr задает адрес
и порт для прослушивания, поле Handler определяет
обработчик всех входящих запросов (если nil, используется
DefaultServeMux), поля ReadTimeout и
WriteTimeout устанавливают ограничения на время
чтения и записи запросов.
Пример
Давайте создадим простой HTTP-сервер с обработчиком, возвращающим приветственное сообщение:
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
server := &http.Server{
Addr: ":8080",
Handler: mux,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
fmt.Println("Server started on :8080")
err := server.ListenAndServe()
if err != nil {
fmt.Println("Server error:", err)
}
}
Результат выполнения при запуске сервера:
"Server started on :8080"
При обращении к http://localhost:8080 в браузере
будет выведено сообщение "Hello, World!".
Пример
Давайте реализуем graceful shutdown сервера с использованием
метода Shutdown, который позволяет корректно
завершить обработку текущих запросов:
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"time"
)
func main() {
server := &http.Server{
Addr: ":8080",
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, graceful shutdown!")
})
go func() {
fmt.Println("Server started on :8080")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
fmt.Printf("ListenAndServe error: %s\n", err)
}
}()
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
<-stop
fmt.Println("Shutting down server...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
fmt.Printf("Shutdown error: %s\n", err)
}
fmt.Println("Server stopped gracefully")
}
Результат выполнения при остановке сервера:
"Shutting down server..."
"Server stopped gracefully"
В этом примере сервер запускается в отдельной горутине,
а основной поток ожидает сигнал прерывания (Ctrl+C).
После получения сигнала вызывается метод Shutdown
с контекстом, ограничивающим время ожидания завершения
текущих запросов.
Пример
Рассмотрим использование метода Close для немедленного
закрытия сервера без ожидания завершения текущих запросов:
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
server := &http.Server{
Addr: ":8080",
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
time.Sleep(5 * time.Second)
fmt.Fprintf(w, "Slow response")
})
go func() {
fmt.Println("Server started on :8080")
if err := server.ListenAndServe(); err != nil {
fmt.Printf("ListenAndServe error: %s\n", err)
}
}()
time.Sleep(2 * time.Second)
fmt.Println("Closing server immediately...")
if err := server.Close(); err != nil {
fmt.Printf("Close error: %s\n", err)
}
fmt.Println("Server closed")
}
Результат выполнения:
"Server started on :8080"
"Closing server immediately..."
"Server closed"
Метод Close закрывает сервер немедленно, прерывая
все текущие соединения. В отличие от Shutdown,
этот метод не ждет завершения обработки текущих запросов.
Смотрите также
-
метод
http.Server.ListenAndServe,
который запускает сервер и начинает прослушивание -
метод
http.Server.Shutdown,
который выполняет graceful остановку сервера -
метод
http.Server.Close,
который немедленно закрывает сервер -
функцию
http.ListenAndServe,
которая запускает сервер с настройками по умолчанию