A Go HTTP client's transport selects the proxy. Clone the standard transport before changing it so other users of the default client keep their existing routing.

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "net/url"
    "time"
)

func main() {
    proxyURL, err := url.Parse("http://203.0.113.10:8080")
    if err != nil {
        log.Fatal(err)
    }

    transport := http.DefaultTransport.(*http.Transport).Clone()
    transport.Proxy = http.ProxyURL(proxyURL)
    defer transport.CloseIdleConnections()

    client := &http.Client{
        Transport: transport,
        Timeout:   15 * time.Second,
    }

    response, err := client.Get("https://example.com/")
    if err != nil {
        log.Fatal(err)
    }
    defer response.Body.Close()

    fmt.Println(response.StatusCode)
    if _, err := io.Copy(io.Discard, response.Body); err != nil {
        log.Fatal(err)
    }
}

The address is a documentation placeholder. Replace it with a real HTTP proxy IP and port, such as a candidate selected from the HTTP proxy list. The example uses only Go's standard library; no SOCKS package or process-wide environment variable is needed for this HTTP proxy request.

Why not change DefaultTransport directly?

The default transport is shared. Mutating it can change the behavior of code that never asked to use your proxy, and changing a transport while requests are using it introduces avoidable concurrency problems. A dedicated transport makes the route part of this client's configuration.

http.ProxyURL returns a selector that consistently chooses the supplied URL. This differs from the default environment selector, which considers proxy variables and bypass rules. If your intention is to test one particular HTTP list entry, the explicit selector removes that source of ambiguity.

Close the response and reuse the client

The example drains and closes the response body. Reading the body to completion helps the transport reuse a connection when it can. In a program making several requests through the same proxy, retain the client and transport rather than constructing a new pair for every request.

The client's timeout covers more than opening the socket; it also bounds the request lifecycle, including response-body reading. Read errors still need handling after Get returns. A status such as 403 is not a Go transport error, so inspect StatusCode separately from err.

Аффингæй хæстæг статьялтæ