When building URLs in Go, especially those containing query parameters, it’s crucial to handle parameter encoding correctly. A common mistake is concatenating query parameters directly to the URL string, which can lead to issues with special characters and improper URL formatting.

The Problem

Consider this seemingly simple code:

func UrlInitState() string {
    u, _ := url.JoinPath(env.NexusApiRoot(), "/v1/init?action=check")
    return u
}

While this might work for basic cases, it has several potential issues:

  • Special characters in parameter values won’t be properly encoded
  • Multiple parameters become harder to manage
  • The code becomes more error-prone as complexity increases

The Solution

Instead, use Go’s url.Values type to properly handle query parameters:

func UrlInitState() string {
    base, _ := url.JoinPath(env.NexusApiRoot(), "/v1/init")
    params := url.Values{}
    params.Add("action", "check")
    return base + "?" + params.Encode()
}

This approach offers several benefits:

  1. Automatic proper encoding of special characters
  2. Easy addition of multiple parameters
  3. Clean separation between the base URL and query parameters
  4. Built-in validation and encoding handling

Advanced Usage

For more complex scenarios, you can add multiple parameters:

func BuildComplexURL() string {
    base, _ := url.JoinPath(env.NexusApiRoot(), "/v1/search")
    params := url.Values{}
    params.Add("q", "search term with spaces")
    params.Add("category", "books&movies")  // Special characters handled automatically
    params.Add("limit", "50")
    return base + "?" + params.Encode()
}

Best Practices

  • Always use url.Values for query parameters
  • Separate base URL construction from parameter handling
  • Handle errors from url.JoinPath appropriately in production code
  • Consider using url.Parse and url.URL for more complex URL manipulation

Remember: URL encoding isn’t just about making URLs look nice – it’s about ensuring your applications handle data correctly and securely.