Зачем использовать прокси в 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.






