Использование прокси в Go: HTTP-клиент и SDK

Узнайте, как настроить прокси в Go с помощью net/http и ProxyHat Go SDK. Примеры кода для аутентификации, ротации, геотаргетинга, конкурентного скрапинга горутинами и лучшие практики для продакшна.

Использование прокси в Go: HTTP-клиент и SDK

Зачем использовать прокси в Go?

Go стал языком первого выбора для создания высокопроизводительных сетевых инструментов, веб-скраперов и API-клиентов. Легковесные горутины, встроенные примитивы конкурентности и проверенная временем стандартная библиотека net/http делают его идеальным для приложений с прокси, которым нужно обрабатывать тысячи параллельных запросов.

Независимо от того, строите ли вы конвейер для веб-скрапинга, отслеживаете позиции в поисковой выдаче или собираете данные о ценах конкурентов — маршрутизация HTTP-клиентов Go через прокси позволяет ротировать IP-адреса, обходить географические ограничения и избегать лимитов частоты запросов в промышленных масштабах.

В этом руководстве вы узнаете, как настроить прокси в Go с помощью стандартной библиотеки и ProxyHat Go SDK. Все примеры кода готовы к копированию — вы сможете начать скрапинг за считанные минуты.

Установка

ProxyHat Go SDK

Самый быстрый способ начать — использовать официальный SDK. Он берёт на себя аутентификацию, ротацию, геотаргетинг и повторные попытки прямо из коробки.

go get github.com/ProxyHatCom/go-sdk@latest

Только стандартная библиотека

Если вы предпочитаете обходиться без внешних зависимостей, пакетов net/http и net/url из стандартной библиотеки Go будет достаточно. Никакой дополнительной установки не потребуется.

Аутентификация и базовая настройка

ProxyHat использует аутентификацию по логину и паролю через прокси-эндпоинт. Учётные данные можно найти в панели управления ProxyHat. Типичный URL прокси выглядит так:

http://USERNAME:PASSWORD@gate.proxyhat.com:8080

Не храните учётные данные в исходном коде. Используйте переменные окружения или файл .env:

export PROXYHAT_USER="your_username"
export PROXYHAT_PASS="your_password"

Простой GET-запрос через прокси

Вот минимальный вариант с использованием только стандартной библиотеки:

package main
import (
    "fmt"
    "io"
    "log"
    "net/http"
    "net/url"
    "os"
)
func main() {
    proxyURL, err := url.Parse(fmt.Sprintf(
        "http://%s:%s@gate.proxyhat.com:8080",
        os.Getenv("PROXYHAT_USER"),
        os.Getenv("PROXYHAT_PASS"),
    ))
    if err != nil {
        log.Fatal(err)
    }
    client := &http.Client{
        Transport: &http.Transport{
            Proxy: http.ProxyURL(proxyURL),
        },
    }
    resp, err := client.Get("https://httpbin.org/ip")
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))
}

Запустите программу, и вместо вашего собственного IP вы увидите резидентный IP-адрес. Каждый запрос проходит через пул резидентных прокси ProxyHat.

Типы прокси

ProxyHat поддерживает три типа прокси, каждый из которых подходит для определённых задач. Тип выбирается через порт или флаг в имени пользователя:

ТипПортПодходит дляСредняя задержка
Резидентные8000Веб-скрапинг, верификация рекламы~800 мс
Датацентр8010Высокоскоростные массовые запросы~200 мс
Мобильные8020Соцсети, тестирование приложений~1200 мс

Подробное сравнение типов прокси и рекомендации по выбору читайте в нашем руководстве резидентные, датацентр и мобильные прокси.

// Switch proxy type by changing the port
residentialProxy := "http://user:pass@gate.proxyhat.com:8080"
datacenterProxy  := "http://user:pass@gate.proxyhat.com:8080"
mobileProxy      := "http://user:pass@gate.proxyhat.com:8080"

Ручная настройка: Go net/http с конфигурацией прокси

Для полного контроля настройте http.Transport напрямую. Это позволяет тонко регулировать пул соединений, параметры TLS и таймауты:

package main
import (
    "crypto/tls"
    "net/http"
    "net/url"
    "time"
)
func newProxyClient(proxyAddr string) (*http.Client, error) {
    proxyURL, err := url.Parse(proxyAddr)
    if err != nil {
        return nil, err
    }
    transport := &http.Transport{
        Proxy:               http.ProxyURL(proxyURL),
        MaxIdleConns:        100,
        MaxIdleConnsPerHost: 10,
        IdleConnTimeout:     90 * time.Second,
        TLSClientConfig:     &tls.Config{MinVersion: tls.VersionTLS12},
    }
    client := &http.Client{
        Transport: transport,
        Timeout:   30 * time.Second,
    }
    return client, nil
}

Рекомендуемый подход: ProxyHat Go SDK

ProxyHat Go SDK инкапсулирует весь шаблонный код в лаконичный API. Он самостоятельно управляет пулом соединений, автоматическими повторами, сессиями и геотаргетингом.

package main
import (
    "context"
    "fmt"
    "log"
    proxyhat "github.com/ProxyHatCom/go-sdk"
)
func main() {
    client, err := proxyhat.NewClient(proxyhat.Config{
        Username:  "your_username",
        Password:  "your_password",
        ProxyType: proxyhat.Residential,
    })
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
    resp, err := client.Get(context.Background(), "https://httpbin.org/ip")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Status:", resp.StatusCode)
    fmt.Println("Body:", string(resp.Body))
}

SDK возвращает структурированный ответ, автоматически обрабатывает декомпрессию и повторяет запросы при временных сбоях. Полный справочник методов доступен в документации API.

Ротация и sticky-сессии

ProxyHat поддерживает два режима работы сессий:

  • Ротация (по умолчанию) — каждый запрос получает новый IP-адрес. Идеально для масштабного веб-скрапинга.
  • Sticky-сессии — один и тот же IP удерживается на настраиваемый период (до 30 минут). Подходит для многошаговых сценариев: авторизация, пагинация, последовательный обход страниц.

Ротация сессий (SDK)

client, _ := proxyhat.NewClient(proxyhat.Config{
    Username:  "your_username",
    Password:  "your_password",
    ProxyType: proxyhat.Residential,
    // Rotating is the default — no extra config needed
})
// Each call uses a different IP
for i := 0; i < 5; i++ {
    resp, _ := client.Get(context.Background(), "https://httpbin.org/ip")
    fmt.Printf("Request %d: %s\n", i+1, string(resp.Body))
}

Sticky-сессии (SDK)

session, _ := client.NewSession(proxyhat.SessionConfig{
    Duration: 10 * time.Minute,
})
// All requests through this session use the same IP
resp1, _ := session.Get(context.Background(), "https://example.com/login")
resp2, _ := session.Post(context.Background(), "https://example.com/dashboard", payload)

Sticky-сессии (ручной способ)

// Append session ID to the username
// Format: USERNAME-session-SESSIONID
proxyURL := "http://user-session-abc123:pass@gate.proxyhat.com:8080"

Геотаргетинг запросов

Нужны IP-адреса из определённой страны? ProxyHat поддерживает 190+ локаций. Передайте код страны через SDK или в виде флага в имени пользователя:

// SDK approach
client, _ := proxyhat.NewClient(proxyhat.Config{
    Username:  "your_username",
    Password:  "your_password",
    ProxyType: proxyhat.Residential,
    Country:   "US",   // ISO 3166-1 alpha-2
    State:     "CA",   // optional: state/region
    City:      "LA",   // optional: city
})
resp, _ := client.Get(context.Background(), "https://httpbin.org/ip")
fmt.Println(string(resp.Body)) // US-based IP
// Manual approach — append country to username
// Format: USERNAME-country-US
proxyURL := "http://user-country-US:pass@gate.proxyhat.com:8080"

Геотаргетинг необходим для локализованного отслеживания поисковой выдачи, проверки региональных цен и тестирования доступности контента.

Обработка ошибок и повторные попытки

Сетевые запросы через прокси могут завершаться неудачей по временным причинам: сброс соединения, таймауты или временные блокировки. Надёжная обработка ошибок критически важна для продакшн-скраперов.

Встроенные повторы в SDK

client, _ := proxyhat.NewClient(proxyhat.Config{
    Username:   "your_username",
    Password:   "your_password",
    ProxyType:  proxyhat.Residential,
    MaxRetries: 3,
    RetryDelay: 2 * time.Second,
})

Ручной повтор с экспоненциальной задержкой

package main
import (
    "fmt"
    "math"
    "net/http"
    "time"
)
func fetchWithRetry(client *http.Client, url string, maxRetries int) (*http.Response, error) {
    var lastErr error
    for attempt := 0; attempt <= maxRetries; attempt++ {
        resp, err := client.Get(url)
        if err == nil && resp.StatusCode < 500 {
            return resp, nil
        }
        if err != nil {
            lastErr = err
        } else {
            lastErr = fmt.Errorf("HTTP %d", resp.StatusCode)
            resp.Body.Close()
        }
        backoff := time.Duration(math.Pow(2, float64(attempt))) * time.Second
        time.Sleep(backoff)
    }
    return nil, fmt.Errorf("all %d retries failed: %w", maxRetries, lastErr)
}

Параллельный скрапинг с горутинами

Модель конкурентности Go — его главное преимущество. С помощью горутин и каналов можно одновременно обрабатывать сотни URL при минимальном потреблении памяти.

package main
import (
    "context"
    "fmt"
    "sync"
    proxyhat "github.com/ProxyHatCom/go-sdk"
)
type Result struct {
    URL        string
    StatusCode int
    Body       string
    Err        error
}
func scrape(ctx context.Context, client *proxyhat.Client, urls []string, concurrency int) []Result {
    results := make([]Result, len(urls))
    sem := make(chan struct{}, concurrency) // semaphore
    var wg sync.WaitGroup
    for i, u := range urls {
        wg.Add(1)
        go func(idx int, target string) {
            defer wg.Done()
            sem <- struct{}{}        // acquire
            defer func() { <-sem }() // release
            resp, err := client.Get(ctx, target)
            if err != nil {
                results[idx] = Result{URL: target, Err: err}
                return
            }
            results[idx] = Result{
                URL:        target,
                StatusCode: resp.StatusCode,
                Body:       string(resp.Body),
            }
        }(i, u)
    }
    wg.Wait()
    return results
}
func main() {
    client, _ := proxyhat.NewClient(proxyhat.Config{
        Username:  "your_username",
        Password:  "your_password",
        ProxyType: proxyhat.Residential,
    })
    defer client.Close()
    urls := []string{
        "https://example.com/page/1",
        "https://example.com/page/2",
        "https://example.com/page/3",
        // ... hundreds more
    }
    results := scrape(context.Background(), client, urls, 20)
    for _, r := range results {
        if r.Err != nil {
            fmt.Printf("FAIL %s: %v\n", r.URL, r.Err)
        } else {
            fmt.Printf("OK   %s: %d bytes\n", r.URL, len(r.Body))
        }
    }
}

Ограничение частоты запросов с помощью семафора

В скрапере выше уже используется канал-семафор для ограничения конкурентности. Для более точного контроля частоты (например, N запросов в секунду) используйте пакет golang.org/x/time/rate:

package main
import (
    "context"
    "fmt"
    "log"
    proxyhat "github.com/ProxyHatCom/go-sdk"
    "golang.org/x/time/rate"
)
func main() {
    client, _ := proxyhat.NewClient(proxyhat.Config{
        Username:  "your_username",
        Password:  "your_password",
        ProxyType: proxyhat.Residential,
    })
    defer client.Close()
    // Allow 10 requests per second, burst of 20
    limiter := rate.NewLimiter(10, 20)
    urls := []string{"https://example.com/1", "https://example.com/2"}
    for _, u := range urls {
        if err := limiter.Wait(context.Background()); err != nil {
            log.Fatal(err)
        }
        resp, err := client.Get(context.Background(), u)
        if err != nil {
            fmt.Printf("Error: %v\n", err)
            continue
        }
        fmt.Printf("%s — %d\n", u, resp.StatusCode)
    }
}

Советы для продакшна

Пул соединений

http.Transport в Go по умолчанию поддерживает пул неактивных соединений. Для работы с прокси настройте следующие параметры:

transport := &http.Transport{
    Proxy:                 http.ProxyURL(proxyURL),
    MaxIdleConns:          200,
    MaxIdleConnsPerHost:   50,
    MaxConnsPerHost:       100,
    IdleConnTimeout:       90 * time.Second,
    ResponseHeaderTimeout: 15 * time.Second,
}

Таймауты

Всегда устанавливайте таймауты. Скрапер без таймаутов рано или поздно зависнет на заблокированном соединении:

client := &http.Client{
    Transport: transport,
    Timeout:   30 * time.Second, // total request timeout
}
// Or use context for per-request control
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", targetURL, nil)
resp, err := client.Do(req)

Корректное завершение работы

В долгоживущих скраперах перехватывайте сигналы ОС для корректного завершения:

package main
import (
    "context"
    "os"
    "os/signal"
    "syscall"
)
func main() {
    ctx, stop := signal.NotifyContext(
        context.Background(),
        os.Interrupt, syscall.SIGTERM,
    )
    defer stop()
    // Pass ctx to your scraping functions
    // When Ctrl+C is pressed, ctx is cancelled
    // and in-flight requests wind down gracefully
    runScraper(ctx)
}

Логирование и наблюдаемость

Оберните HTTP-транспорт для логирования времени выполнения запросов и кодов ответов. Это помогает выявлять медленные цели и ошибки прокси в продакшне:

type loggingTransport struct {
    inner http.RoundTripper
}
func (t *loggingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    start := time.Now()
    resp, err := t.inner.RoundTrip(req)
    elapsed := time.Since(start)
    if err != nil {
        log.Printf("ERR  %s %s (%v) err=%v", req.Method, req.URL, elapsed, err)
    } else {
        log.Printf("OK   %s %s (%v) status=%d", req.Method, req.URL, elapsed, resp.StatusCode)
    }
    return resp, err
}

Ключевые выводы

  • Горутины Go + прокси = массивная конкурентность. Вы можете выполнять тысячи запросов через прокси с минимальным потреблением памяти.
  • ProxyHat Go SDK берёт на себя аутентификацию, повторы, сессии и геотаргетинг через удобный API. Установите его, чтобы не писать шаблонный код.
  • Используйте ротацию IP для масштабного скрапинга и sticky-сессии для многошаговых сценариев вроде авторизации.
  • Всегда устанавливайте таймауты как на уровне http.Client, так и через context.WithTimeout для контроля отдельных запросов.
  • Ограничивайте частоту запросов с помощью golang.org/x/time/rate и контролируйте конкурентность каналами-семафорами.
  • Используйте геотаргетинг, передавая код страны для доступа к 190+ локациям по всему миру.
  • Ознакомьтесь с нашим руководством по лучшим прокси для веб-скрапинга, чтобы выбрать подходящий тариф.

Часто задаваемые вопросы

Как настроить прокси в Go-клиенте net/http?

Установите поле Proxy в http.Transport равным http.ProxyURL(parsedURL), где parsedURL — адрес вашего прокси, разобранный через url.Parse(). Затем передайте транспорт в http.Client. Стандартная библиотека автоматически обрабатывает CONNECT-туннелирование для HTTPS-целей.

Поддерживает ли ProxyHat Go SDK работу с HTTPS?

Да. SDK использует HTTP CONNECT-туннелирование, поэтому весь HTTPS-трафик зашифрован от вашего клиента до целевого сервера. Прокси видит только имя хоста назначения.

Сколько параллельных запросов можно отправлять через прокси в Go?

Горутины Go чрезвычайно легковесны (примерно 4 КБ стека каждая), поэтому вы можете запускать десятки тысяч одновременно. Практический предел определяется лимитом параллельных соединений вашего тарифа ProxyHat и возможностями целевого сервера. Используйте канал-семафор для ограничения конкурентности на безопасном уровне.

В чём разница между ротацией и sticky-сессиями прокси?

При ротации каждому запросу назначается новый IP-адрес — это оптимально для массового скрапинга. Sticky-сессии сохраняют один и тот же IP на заданный период (до 30 минут), что подходит для многошаговых сценариев, где целевой сайт ожидает постоянного посетителя: авторизация, оформление заказа и т.д.

Как обрабатывать ошибки прокси и повторные попытки в Go?

ProxyHat Go SDK предоставляет встроенную логику повторов с настраиваемыми MaxRetries и RetryDelay. При использовании стандартной библиотеки реализуйте экспоненциальную задержку: оберните запрос в цикл, удваивая паузу после каждой неудачной попытки. Всегда проверяйте как сетевые ошибки, так и HTTP-статусы 5xx.

Готовы начать?

Доступ к более чем 50 млн резидентных IP в 148+ странах с AI-фильтрацией.

Смотреть ценыРезидентные прокси
← Вернуться в Блог