Пример: HTTP-сервер
Собираем небольшой HTTP-сервер с JSON API на одной только стандартной библиотеке.
Пакет
net/httpпозволяет написать рабочий веб-сервер в несколько строк — без фреймворков. Это показывает, насколько Go заточен под сетевые сервисы.
Сервер «Hello» в десять строк
Минимальный сервер регистрирует обработчик на путь и слушает порт. Обработчик — функция, получающая ResponseWriter (куда писать ответ) и *Request (данные запроса).
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Привет, %s!", r.URL.Path[1:])
})
fmt.Println("слушаю :8080")
http.ListenAndServe(":8080", nil)
}go run main.go
# в другом терминале:
curl http://localhost:8080/GoВывод:
Привет, Go!
http.HandleFunc связывает путь с функцией, ListenAndServe запускает сервер. Каждый запрос Go обрабатывает в отдельной горутине автоматически — конкурентность здесь бесплатна.
JSON API: чуть ближе к реальности
Соберём эндпоинт, который отдаёт JSON. Объединим то, что уже знаем: структуры, теги JSON и encoding/json.
package main
import (
"encoding/json"
"net/http"
)
type Status struct {
Service string `json:"service"`
OK bool `json:"ok"`
}
func statusHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
s := Status{Service: "api", OK: true}
json.NewEncoder(w).Encode(s)
}
func main() {
http.HandleFunc("/status", statusHandler)
http.ListenAndServe(":8080", nil)
}curl http://localhost:8080/statusВывод:
{"service":"api","ok":true}Мы выставили заголовок Content-Type и закодировали структуру прямо в поток ответа через json.NewEncoder(w).Encode. Никаких внешних библиотек — всё из стандартной поставки.
Маршрутизация по методам
В реальном API разные HTTP-методы делают разное. Их различают по r.Method. Современный Go (1.22+) умеет даже задавать метод прямо в паттерне: http.HandleFunc("POST /users", ...).
func usersHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
w.Write([]byte("список пользователей"))
case http.MethodPost:
w.WriteHeader(http.StatusCreated)
w.Write([]byte("пользователь создан"))
default:
http.Error(w, "метод не поддерживается", http.StatusMethodNotAllowed)
}
}Что дальше с веб-сервисами
Этого достаточно для простых сервисов. Для крупных API берут роутеры (chi, gorilla/mux) или фреймворки (Gin, Echo), но даже они построены поверх того же net/http. Понимание базы делает их освоение лёгким.
Итог
- Рабочий HTTP-сервер пишется на
net/httpбез фреймворков. - Каждый запрос Go обрабатывает в своей горутине — конкурентность встроена.
- JSON-ответ — связка структуры с тегами и
json.NewEncoder(w).Encode.