URL Parsing
net/url.Parse to decompose URLs, url.URL fields for scheme, host, path, and query, url.Values for safe query parameter encoding.
The net/url package parses and builds URLs safely. url.Parse decomposes a raw URL string into its components; url.Values encodes query parameters without manual escaping.
url.Parse returns a *url.URL with fields for each component. All fields are strings - no type conversion needed. An error is only returned for malformed input that cannot be parsed at all; many "bad" URLs still parse without error.
package main
import (
"fmt"
"net/url"
)
func main() {
u, err := url.Parse("https://api.example.com:8080/v1/users?page=2&limit=50#results")
if err != nil {
panic(err)
}
fmt.Println(u.Scheme) // https
fmt.Println(u.Host) // api.example.com:8080
fmt.Println(u.Path) // /v1/users
fmt.Println(u.RawQuery) // page=2&limit=50
fmt.Println(u.Fragment) // results
}url.URL.Query() parses the raw query string into a url.Values map. Use it to read individual parameters. url.Values.Encode() serialises back to a query string, sorting keys alphabetically for deterministic output.
package main
import (
"fmt"
"net/url"
)
func main() {
u, _ := url.Parse("https://search.example.com?q=golang+channels&sort=date&page=1")
params := u.Query()
fmt.Println(params.Get("q")) // golang channels
fmt.Println(params.Get("sort")) // date
// Build a new query string safely
v := url.Values{}
v.Set("q", "go generics <1.18")
v.Set("sort", "relevance")
fmt.Println(v.Encode()) // q=go+generics+%3C1.18&sort=relevance
}u.Hostname() strips the port from Host, and u.Port() extracts just the port. Use these instead of splitting Host manually to handle IPv6 addresses correctly.
package main
import (
"fmt"
"net/url"
)
func main() {
u, _ := url.Parse("https://api.example.com:8080/health")
fmt.Println(u.Hostname()) // api.example.com
fmt.Println(u.Port()) // 8080
// Rebuild the URL with a different path
u.Path = "/v2/health"
fmt.Println(u.String()) // https://api.example.com:8080/v2/health
}In production
Always parse user-supplied URLs with url.Parse before use - do not string-concatenate URLs or use fmt.Sprintf to build query strings. Use url.Values.Encode() to safely encode query parameters; it handles special characters correctly and sorts keys deterministically, making URLs easier to cache and compare. When constructing outbound API URLs in production code, build a url.URL struct from components rather than formatting a string: it prevents accidental double-encoding and makes the code easier to read and test. For path segments that may contain slashes or special characters, use url.PathEscape rather than url.QueryEscape - they escape different character sets.
Enjoyed this? Get more essays on software craft delivered to your inbox.
Subscribe free