A SOCKS tunnel carries a TCP connection. Go can perform TLS with the destination through that tunnel and negotiate HTTP/2 there; the SOCKS server does not need to speak HTTP/2 itself.

In a program retaining Go’s standard default transport, clone its configuration and select the proxy:

import (
    "net/http"
    "net/url"
    "time"
)

proxyURL := &url.URL{
    Scheme: "socks5",
    Host: "proxy.example:1080",
}
transport := http.DefaultTransport.(*http.Transport).Clone()
transport.Proxy = http.ProxyURL(proxyURL)
client := &http.Client{
    Transport: transport,
    Timeout: 30 * time.Second,
}

The proxy and destination remain different values. Select a SOCKS5 endpoint from the SOCKS5 proxy list for the proxy value; HTTP/2 is still negotiated with the destination. Use client to request the real HTTPS service URL, then close the response body through the application’s normal lifecycle.

The standard default transport supports HTTP/2. Cloning it retains that configuration while allowing the proxy choice to change. The type assertion assumes the program has not replaced http.DefaultTransport with another RoundTripper.

For a separately constructed transport, review its HTTP/2 configuration, especially when supplying custom dial or TLS hooks. Go exposes ForceAttemptHTTP2 and, in newer releases, explicit Protocols configuration for those choices.

The destination still has to offer HTTP/2 through TLS negotiation. Inspect the successful response’s Proto or ProtoMajor value to see what was used. An HTTPS request succeeding through SOCKS does not by itself establish that the negotiated protocol was HTTP/2.

Mikanda mikatakata