Глиф Учебники

Как сделать HTTP-сервер на Go

Справочник · Go · 2 минуты чтения

В Go HTTP-сервер есть в стандартной библиотеке — пакет net/http. Ставить ничего не нужно:

Go
package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "time"
)

func main() {
    http.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Главная страница")
    })

    http.HandleFunc("GET /hello/{name}", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Привет, %s!\n", r.PathValue("name"))
    })

    http.HandleFunc("GET /api/time", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(map[string]string{"time": time.Now().Format(time.RFC3339)})
    })

    log.Println("сервер запущен: http://localhost:8080")
    log.Fatal(http.ListenAndServe("localhost:8080", nil))
}

Сохраните как main.go в папке модуля и запустите go run .. Сервер работает, пока его не остановить сочетанием Ctrl+C. Проверьте в браузере http://localhost:8080/hello/anna или из второго окна терминала программой curl (она отправляет запрос и печатает ответ):

Терминал
$ curl http://localhost:8080/hello/anna
Привет, anna!

В Windows PowerShell слово curl может означать другую команду (Invoke-WebRequest) — набирайте curl.exe.

Как это устроено

Шаблоны адресов (Go 1.22 и новее)

Методы и {параметры} в шаблонах появились в Go 1.22. Они работают, если в go.mod указана версия go 1.22 или новее. В примерах для старых версий метод проверяют вручную: if r.Method != http.MethodGet { … }.

Ошибки и коды ответа

Код ответа задают до того, как писать тело. Для ошибок есть готовая функция:

Go
http.Error(w, "товар не найден", http.StatusNotFound)

Она отправит код 404 и текст. Без явного кода сервер отвечает 200 OK.

Адрес: свой компьютер или вся сеть

"localhost:8080" — сервер доступен только с этого же компьютера. Так безопасно для разработки.

Адрес ":8080" (без имени) открывает сервер для всех сетей компьютера: его увидят другие устройства в локальной сети, а на сервере с внешним адресом — весь интернет. Открывайте порт наружу, только когда это действительно нужно, и не выставляйте в сеть отладочные адреса без пароля.

На сервере Linux порт закрывают и открывают брандмауэром (фильтром сетевых подключений) — для Ubuntu это справка Как открыть порт в Ubuntu.

Если не запускается

Для настоящего сервера

http.ListenAndServe не ограничивает время ожидания клиента. Для сервера, открытого в интернет, создают http.Server с таймаутами (пределами времени ожидания), например ReadHeaderTimeout: 5 * time.Second, и вызывают у него ListenAndServe(). Подробности — в документации пакета net/http.