Гид по технологиям

HTTP-запросы в Go: отправка GET, POST, PUT и DELETE

7 min read Программирование Обновлено 13 Dec 2025
HTTP-запросы в Go: GET, POST, PUT, DELETE
HTTP-запросы в Go: GET, POST, PUT, DELETE

Иллюстрация: талисман языка Go (гофер) и значок глобуса с стрелками, показывающими передачу данных.

Что такое HTTP-запрос?

HTTP описывает, как клиент (браузер или приложение) запрашивает ресурс у сервера, а сервер возвращает ответ. Запрос обычно содержит URL ресурса и дополнительные сведения: метод (GET, POST и т. д.), заголовки, параметры строки запроса и, по необходимости, тело запроса.

Краткое определение: HTTP‑запрос — это структурированное сообщение от клиента к серверу, содержащее метод, путь и опциональные данные.

Типичные методы: GET (получить), POST (создать), PUT (обновить целиком), PATCH (частичное обновление), DELETE (удалить), HEAD, OPTIONS, CONNECT.

PUT и PATCH часто используют для обновления: PUT обычно заменяет ресурс целиком, PATCH — вносит частичное изменение. На практике различия зависят от API.

Отправка запросов в Go — общая идея

Пакет net/http предоставляет набор типов и функций для создания запросов и получения ответов. Базовый паттерн:

  • Создаёте запрос с http.NewRequest(method, url, body).
  • Настраиваете заголовки (Content-Type, Authorization и т.д.).
  • Передаёте запрос клиенту (http.Client) методом Do.
  • Читаете response.Body, закрываете его через defer.

Для простых случаев можно использовать http.Get и http.Post, они сокращают шаблон.

Важно: всегда обрабатывать ошибки и закрывать тело ответа (defer response.Body.Close()). В продакшн‑коде дополнительно задавайте таймауты и контекст.

Примеры: использование reqres.in для тестов

Ниже приведены примеры функций на Go, которые отправляют POST, GET, PUT и DELETE через API reqres.in. Код оставлен практически без изменений для наглядности — в реальном проекте оборачивайте повторяющиеся операции (создание запросов, чтение тела, логирование) в вспомогательные функции.

POST

Функция создаёт пользователя через POST /api/users.

        `package main  
  
import (  
bytes"  
encoding/json"  
fmt"  
io"  
net/http"  
)  
  
funccreateUser(name, job string) {  
fmt.Println("Creating user...")  
  
apiUrl := "https://reqres.in/api/users"  
userData := []byte(`{"name":"` + name + `","job":"` + job + `"}`)  
  
// create new http request  
request, error := http.NewRequest("POST", apiUrl, bytes.NewBuffer(userData))  
request.Header.Set("Content-Type", "application/json; charset=utf-8")  
  
// send the request  
client := &http.Client{}  
response, error := client.Do(request)  
  
if error != nil {  
fmt.Println(error)  
}  
  
responseBody, error := io.ReadAll(response.Body)  
  
if error != nil {  
fmt.Println(error)  
}  
  
formattedData := formatJSON(responseBody)  
fmt.Println("Status: ", response.Status)  
fmt.Println("Response body: ", formattedData)  
  
// clean up memory after execution  
defer response.Body.Close()  
}  
`
    

Функция formatJSON, которая форматирует JSON для вывода, выглядит так:

        `// function to format JSON data  
funcformatJSON(data []byte) string {  
var out bytes.Buffer  
err := json.Indent(&out, data, "", "  ")  
  
if err != nil {  
fmt.Println(err)  
}  
  
d := out.Bytes()  
returnstring(d)  
}  
`
    

Вызов:

        `funcmain() {  
fmt.Println("Making POST request...")  
createUser("Tim Omolana", "Writer")  
}  
`
    

Вывод программы (пример):

Вывод программы с POST-запросом

GET

Функция получает пользователя по ID через GET /api/users/{id}.

        `// main.go  
funcgetUser(id string) {  
fmt.Println("Getting user by ID...")  
  
// make GET request to API to get user by ID  
apiUrl := "https://reqres.in/api/users/" + id  
request, error := http.NewRequest("GET", apiUrl, nil)  
  
if error != nil {  
fmt.Println(error)  
}  
  
request.Header.Set("Content-Type", "application/json; charset=utf-8")  
  
client := &http.Client{}  
response, error := client.Do(request)  
  
if error != nil {  
fmt.Println(error)  
}  
  
responseBody, error := io.ReadAll(response.Body)  
  
if error != nil {  
fmt.Println(error)  
}  
  
formattedData := formatJSON(responseBody)  
fmt.Println("Status: ", response.Status)  
fmt.Println("Response body: ", formattedData)  
  
// clean up memory after execution  
defer response.Body.Close()  
}  
`
    

Пример вызова:

        `funcmain() {  
fmt.Println("Making GET request...")  
getUser("2")  
}  
`
    

Вывод программы (пример):

Вывод программы с GET-запросом

Замечание: GET обычно не имеет тела запроса — данные передаются в URL или через заголовки.

PUT

PUT похож на POST, но чаще используется для обновления существующего ресурса. Обратите внимание, что для обновления обычно добавляют ID в путь.

        `// main.go  
funcupdateUser(name, job, id string) {  
fmt.Println("Updating user...")  
  
// make PUT request to API to update user  
apiUrl := "https://reqres.in/api/users/" + id  
userData := []byte(`{"name":"` + name + `","job":"` + job + `"}`)  
  
// create new http PUT request  
request, error := http.NewRequest("PUT", apiUrl, bytes.NewBuffer(userData))  
request.Header.Set("Content-Type", "application/json; charset=utf-8")  
  
// Remaining function body from createUser function...  
// Make request, get response, and clear memory...  
}  
`
    

Вызов:

        `func main() {  
// update entry with the ID 2.  
updateUser("Tim Newname", "Staff Writer", "2")  
}  
`
    

Пример вывода (иллюстрация):

Вывод программы с примером PUT-запроса

DELETE

DELETE удаляет ресурс по указанному URI. Часто ответ содержит только статус выполнения.

        `funcdeleteUser(id string) {  
fmt.Println("Deleting user...")  
// make DELETE request to API to delete user  
apiUrl := "https://reqres.in/api/users/" + id  
  
// create new http request  
request, error := http.NewRequest("DELETE", apiUrl, nil)  
request.Header.Set("Content-Type", "application/json; charset=utf-8")  
  
client := &http.Client{}  
response, error := client.Do(request)  
if error != nil {  
fmt.Println(error)  
}  
  
fmt.Println("Status: ", response.Status)  
}  
`
    

Пример вызова:

        `funcmain() {  
fmt.Println("Making DELETE request...")  
deleteUser("2")  
}  
`
    

Вывод программы (пример):

Вывод программы с примером DELETE-запроса

Совет: для быстрого прототипирования используйте http.Post и http.Get, но в продакшне чаще нужен клиент с заданным таймаутом и политикой повторных попыток.

Практические рекомендации и антипаттерны

Обработка ошибок и освобождение ресурсов

  • Всегда проверяйте ошибки после http.NewRequest и client.Do.
  • Закрывайте response.Body через defer сразу после проверки ошибки: defer response.Body.Close().
  • Не полагайтесь на автоматическое чтение — читайте тело и при необходимости ограничивайте размер через io.LimitReader.

Таймауты и контекст

  • Создавайте http.Client с Timeout (например, 5–30 секунд в зависимости от ситуации).
  • Для отмены запроса используйте context.Context: кроме контроля времени, это позволяет прерывать запрос при остановке сервиса.

Пример создания клиента с таймаутом:

  • client := &http.Client{Timeout: 10 * time.Second}

Повторные попытки и идемпотентность

  • GET, PUT, DELETE часто допускают повторные попытки; POST обычно нет (может создать дубликат).
  • Для надёжности используйте стратегию экспоненциального бэкоффа и уникальные idempotency‑ключи для операций создания.

Различие между http.Get/http.Post и http.NewRequest

  • http.Get/http.Post удобны для прототипов и простых сценариев.
  • http.NewRequest + client.Do даёт полный контроль: заголовки, метод, тело, контекст.

Безопасность и надёжность

  • Всегда используйте HTTPS для обмена личными данными.
  • Проверяйте и обновляйте сертификаты TLS в окружении. Не отключайте проверку сертификата в продакшне.
  • Устанавливайте заголовки безопасности (Content-Security-Policy на стороне сервера, если релевантно).
  • Валидируйте и ограничивайте размеры входящих/исходящих тел.

Приватность и соответствие требованиям

  • Если вы отправляете или получаете персональные данные (имена, email, идентификаторы), проверьте, соответствует ли обработка данным политике конфиденциальности и локальным требованиям (например, GDPR).
  • Анонимизируйте или шифруйте данные при передаче и хранении.

Когда этот подход не подходит

  • Для высокопроизводительных потоковых API (Server-Sent Events, WebSocket) нет смысла использовать стандартные синхронные HTTP‑запросы; выбирайте соответствующие протоколы.
  • Для миллисекундных задержек и сотен тысяч запросов в секунду понадобится пул соединений, оптимизация клиента и нагрузочное тестирование.

Контроль качества: Критерии приёмки

  • Запросы выполняются с корректными HTTP‑методами и заголовками.
  • Ошибки сетевого уровня и коды ответа 4xx/5xx логируются и корректно обрабатываются.
  • response.Body всегда закрывается.
  • Для внешних API есть таймауты и стратегия повторных попыток.
  • Личные данные передаются только по HTTPS и находятся под контролем политики приватности.

Мини‑чеклист для ролей

Для разработчика:

  • Использовать context для отмены запросов.
  • Обработать все ошибки и закрыть response.Body.
  • Покрыть ключевые сценарии тестами.

Для DevOps:

  • Настроить мониторинг и метрики (latency, error rate).
  • Контролировать TLS и обновления сертификатов.

Для QA:

  • Проверить поведение при сетевых ошибках и при 4xx/5xx ответах.
  • Выполнить нагрузочные тесты и тесты на таймауты.

Тесты и примеры приёмки

  • Тест: успешный POST возвращает 201/200 и валидный JSON.
  • Тест: при недоступном хосте запрос возвращает ошибку и не блокирует горутину.
  • Тест: при большом теле ответа чтение ограничено и не приводит к OOM.

Короткое объявление (100–200 слов)

HTTP‑клиенты в Go: быстро и надёжно. В этой статье показано, как отправлять GET, POST, PUT и DELETE запросы с помощью пакета net/http. Примеры используют тестовый API reqres.in и демонстрируют создание запроса, установку заголовков, чтение ответа и форматирование JSON. Вы также найдёте рекомендации по таймаутам, использованию контекста, обработке ошибок, безопасности TLS и работе с персональными данными. Статья полезна для разработчиков, которые хотят перейти от простых вызовов http.Get к более контролируемому использованию http.Client и http.NewRequest в боевых приложениях.

Модель принятия решений (Mermaid)

flowchart TD
  A[Нужно сделать HTTP‑запрос?] --> B{Требуется ли сложная конфигурация?}
  B -- Да --> C[Использовать http.NewRequest + http.Client]
  B -- Нет --> D[Использовать http.Get / http.Post]
  C --> E{Нужен таймаут/отмена?}
  E -- Да --> F[Передать context и задать Timeout]
  E -- Нет --> G[Обычный запрос]
  D --> G

Краткая 1‑строчная глоссарий

  • HTTP: протокол передачи гипертекста; метод: действие над ресурсом; net/http: стандартная библиотека Go для HTTP.

Заключение

net/http в Go даёт мощный, но простой в использовании набор инструментов для работы с HTTP. Для прототипов хватит http.Get и http.Post, но для надёжных приложений используйте http.NewRequest, контекст, таймауты и продуманную обработку ошибок. Безопасность (HTTPS, валидация сертификатов) и управление приватностью данных — обязательные элементы при интеграции с внешними API.

Важно: симплифицируйте повторяющиеся операции через вспомогательные функции и библиотечные обёртки, чтобы обеспечить единообразие логики запросов и обработки ответов в проекте.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

SSH и Docker: стоит ли подключаться к контейнерам
DevOps

SSH и Docker: стоит ли подключаться к контейнерам

Перенос и резервное копирование VirtualBox
Виртуализация

Перенос и резервное копирование VirtualBox

Как включить PiP (Картинка в картинке) в Chromium Edge
Браузеры

Как включить PiP (Картинка в картинке) в Chromium Edge

Kubescape: сканирование безопасности Kubernetes
Kubernetes

Kubescape: сканирование безопасности Kubernetes

Как выделять и закрывать несколько вкладок в браузере
Браузерные советы

Как выделять и закрывать несколько вкладок в браузере

Oculus Quest 2: подключение к ПК и настройка Oculus Link
VR

Oculus Quest 2: подключение к ПК и настройка Oculus Link