Сервер вызывает вас
Веб-сервер на Go строится из обработчиков (handlers): функций вида func(w http.ResponseWriter, r *http.Request). Сервер принимает соединения и вызывает ваш обработчик один раз на каждый запрос — в r находится всё о запросе, а всё, что вы записываете в w, становится ответом.
Настоящий сервер запускается вызовом http.ListenAndServe(":8080", mux) и работает бесконечно. В примерах здесь вместо этого используется httptest.NewServer — настоящий сервер на случайном свободном порту, который программа может запустить, использовать и остановить, поэтому каждый пример выполняется и завершается сам.
Первый обработчик
Самый простой обработчик записывает одну строку текста. Всё, что делает API — JSON, коды состояния, маршрутизация — происходит внутри функции такого же вида.
Приветствие из обработчика
Обработчик записывает данные в w; клиент читает ровно это как тело ответа, а статус 200 OK подставляется автоматически.
Вывод: программа на Go и захваченный вывод
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
)
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "привет от сервера")
}
func main() {
server := httptest.NewServer(http.HandlerFunc(hello))
defer server.Close()
resp, _ := http.Get(server.URL + "/")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println("статус:", resp.Status)
fmt.Print("тело: ", string(body))
}
Ответ в формате JSON
Обработчик API делает три вещи: устанавливает заголовок Content-Type, выбирает код состояния и кодирует данные. json.NewEncoder(w).Encode(value) записывает JSON прямо в ответ.
Порядок важен: заголовки нужно установить до того, как записано тело.
Конечная точка с JSON
Обработчик кодирует структуру прямо в объект записи ответа. Клиент получает корректный JSON и правильный тип содержимого — это основа каждой конечной точки в остальной части этой группы.
Вывод: программа на Go и захваченный вывод
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
func userHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(User{ID: 1, Name: "Ana"})
}
func main() {
server := httptest.NewServer(http.HandlerFunc(userHandler))
defer server.Close()
resp, _ := http.Get(server.URL + "/user")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println("статус:", resp.Status)
fmt.Println("тип: ", resp.Header.Get("Content-Type"))
fmt.Print("тело: ", string(body))
}