Ответ
Взаимодействие со сторонними API в Go строится на основе стандартного пакета net/http. Для более удобной работы можно использовать сторонние библиотеки, например, resty.
Базовый алгоритм:
- Создание HTTP-клиента: Используется
http.Client. Рекомендуется настраивать таймаут, чтобы избежать зависания приложения. - Формирование запроса: Создается объект
http.Requestс помощьюhttp.NewRequest(). Здесь указывается метод (GET, POST и т.д.), URL и тело запроса (если необходимо). - Добавление заголовков: Заголовки (например,
Content-Type,Authorization) добавляются к запросу черезreq.Header.Set(). - Отправка запроса: Клиент выполняет запрос с помощью метода
client.Do(req). - Обработка ответа:
- Проверяется статус-код ответа (
resp.StatusCode). - Тело ответа (
resp.Body) читается с помощьюio.ReadAll. - Тело (чаще всего JSON) десериализуется в структуру Go с помощью
json.Unmarshal.
- Проверяется статус-код ответа (
Пример (GET-запрос с таймаутом и заголовком):
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
// Структура для парсинга JSON-ответа
type MyStruct struct {
UserID int `json:"userId"`
ID int `json:"id"`
Title string `json:"title"`
}
func main() {
// 1. Создаем HTTP-клиент с таймаутом
client := &http.Client{Timeout: 10 * time.Second}
// 2. Формируем запрос
req, err := http.NewRequest("GET", "https://jsonplaceholder.typicode.com/todos/1", nil)
if err != nil {
panic(err)
}
// 3. Добавляем заголовки
req.Header.Add("Accept", "application/json")
// 4. Отправляем запрос
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 5. Обрабатываем ответ
if resp.StatusCode != http.StatusOK {
fmt.Println("Error: status code", resp.StatusCode)
return
}
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
var result MyStruct
if err := json.Unmarshal(body, &result); err != nil {
panic(err)
}
fmt.Printf("Результат: %+vn", result)
}
Продвинутые практики (Production-ready):
- Context: Использование
context.WithTimeoutилиcontext.WithCancelдля контроля над жизненным циклом запроса. - Retry-логика: Реализация повторных запросов при временных сбоях сети или сервера (например, с экспоненциальной задержкой).
- Circuit Breaker: Использование паттерна "Предохранитель" (например, с библиотекой
sony/gobreaker) для предотвращения каскадных сбоев. - Логирование: Подробное логирование запросов, ответов и ошибок.
- Метрики: Сбор метрик (время ответа, количество ошибок) для мониторинга.
Ответ 18+ 🔞
А, ну ты смотри, решил пообщаться с внешним миром из своего Go-приложения, да? APIшки всякие дергать, как какой-нибудь интернет-маньяк. Ёпта, ну что ж, расскажу, как это без косяков делается, а то насмотришься кривых примеров и потом будешь как Герасим — «Му-му» говорить, а нихуя не работать будет.
В общем, вся эта движуха крутится вокруг пакета net/http. Это наш родной, отечественный инструмент, типа лома. Можно, конечно, взять какую-нибудь обёртку, вроде resty, чтобы жизнь малиной не казалась, но давай начнём с азов, а то мозги не вынесут.
Базовый план, как не облажаться:
- Клиента создаём.
http.Client— наш боевой конь. Главное — не забудь ему таймаут впихнуть, а то твоё приложение зависнет, как будто оно в депрессии, и будет ждать ответа до второго пришествия.Timeout: 10 * time.Second— святое. - Запрос лепим. Берём
http.NewRequest(). Тыкаем туда метод (GET, POST, да хоть DELETE), URL-адрес (куда стучимся) и тело, если надо (для POST, например). - Шапку надеваем. Заголовки — это как визитка. Без
Content-Type: application/jsonтебя на пороге большинства API просто пошлют нахуй. Добавляются черезreq.Header.Set(). - В бой отправляем. Команда
client.Do(req)— это наш выстрел. Жмём на курок. - Ответ разбираем. Тут самое интересное, а для многих — пиздец.
- Сначала смотрим статус-код (
resp.StatusCode). Если не 200 OK, а что-то вроде 404 или 500 — значит, уже где-то накосячили, и пора грустить. - Читаем тело ответа (
resp.Body) черезio.ReadAll. Не забудь потом это тело закрыть (defer resp.Body.Close()), а то утечка памяти будет — хуже, чем в хрущёвке. - Если ответ в JSON (а он почти всегда в JSON), то парсим эту хуйню в свою родную Go-структуру с помощью
json.Unmarshal. Заранее структуру опиши, с тегами, а то опять «Му-му» получится.
- Сначала смотрим статус-код (
Вот тебе живой пример, как GET-запрос с таймаутом и шапкой сделать:
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
// Структура, в которую будем пихать ответ. Теги — это наше всё.
type MyStruct struct {
UserID int `json:"userId"`
ID int `json:"id"`
Title string `json:"title"`
}
func main() {
// 1. Клиент с таймаутом. 10 секунд — и хватит.
client := &http.Client{Timeout: 10 * time.Second}
// 2. Лепим запрос. GET, вот этот URL, тела нет.
req, err := http.NewRequest("GET", "https://jsonplaceholder.typicode.com/todos/1", nil)
if err != nil {
panic(err) // В продакшене, ясное дело, так не делают. Но ты пока запомни.
}
// 3. Надеваем шапку. Говорим: "Друг, я жду от тебя JSON!"
req.Header.Add("Accept", "application/json")
// 4. Стреляем.
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close() // Закрыть, блядь, не забудь! Это важно!
// 5. Разбираем, что нам прислали.
if resp.StatusCode != http.StatusOK {
fmt.Println("Ой, всё! Код ошибки:", resp.StatusCode)
return
}
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
var result MyStruct
if err := json.Unmarshal(body, &result); err != nil {
panic(err)
}
fmt.Printf("Вот что получилось: %+vn", result)
}
А теперь, для продвинутых юзеров (чтобы в проде не вышло волнение ебать):
- Context, ёпта! Используй
context.WithTimeout. Это чтобы можно было запрос по-человечески отменить, если он затупил, а не ждать, пока таймаут клиента сработает. - Повторные попытки (Retry). Сеть — она такая сука, может глюкнуть. Надо уметь послать запрос ещё разок-другой, если первая попытка обосралась. Желательно с экспоненциальной задержкой, чтобы не заDDOSить сервер.
- Предохранитель (Circuit Breaker). Если удалённый API лег и не встаёт, не надо долбить его запросами каждую секунду. Включи «предохранитель» (библиотека
sony/gobreaker), дай ему передохнуть. Паттерн, блядь, важный! - Логируй всё. Что отправил, что получил, сколько времени заняло. Потом, когда всё ебнется, будешь знать, где искать.
- Метрики. Замеряй время ответа, считай ошибки. Чтобы потом с умным видом на графики смотреть и говорить: «Ага, вот тут у нас сервис начал тормозить, как последняя мартышлюшка».
Вот, вроде всё. Главное — не тупи, закрывай Body и таймауты ставь. А то будет тебе трагедия, как у того Герасима, только с памятью и горой запросов.