Quick tip: Change URL query params in Go
In this short post we're going to discuss how to add, modify or delete URL query string parameters in Go. To illustrate, we'll look at how to change this URL:
https://example.com?name=alice&age=28&gender=female
To this:
https://example.com?name=alice&age=29&occupation=carpenter
If you want to change the URL query string in place:
// Use url.Parse() to parse a string into a *url.URL type. If your URL is
// already a url.URL type you can skip this step.
urlA, err := url.Parse("https://example.com?name=alice&age=28&gender=female")
if err != nil {
log.Fatal(err)
}
// Use the Query() method to get the query string params as a url.Values map.
values := urlA.Query()
// Make the changes that you want using the Add(), Set() and Del() methods. If
// you want to retrieve or check for a specific parameter you can use the Get()
// and Has() methods respectively.
values.Add("occupation", "carpenter")
values.Del("gender")
values.Set("age", strconv.Itoa(29))
// Use the Encode() method to transform the url.Values map into a URL-encoded
// string (like "age=29&name=alice...") and assign it back to the URL. Note
// that the encoded values will be sorted alphabetically based on the parameter
// name.
urlA.RawQuery = values.Encode()
fmt.Printf("urlA: %s", urlA.String())
Running this will print out:
urlA: https://example.com?age=29&name=alice&occupation=carpenter
If you want to create a clone of the URL but with a different query string, while leaving the original URL unchanged, you need to create a copy of the original url.URL
struct first.
There are a couple of ways to do this. You can either re-parse the URL, or you can dereference the original url.URL
and make a copy, like so:
// This is equivalent to: var newUrl url.URL = *originalUrl
newUrl := *originalUrl
When you do this, you create a new newURL
variable of type url.URL
which is initialized to the (dereferenced) value of *originalURL
. This means that newURL
has a different address in memory to originalURL
.
Putting this together, the pattern for creating a new URL with different parameters is:
urlA, err := url.Parse("https://example.com?name=alice&age=28&gender=female")
if err != nil {
log.Fatal(err)
}
// Make a copy of the original url.URL.
urlB := *urlA
// Make the param changes to the new url.URL type...
values := urlB.Query()
values.Add("occupation", "carpenter")
values.Del("gender")
values.Set("age", strconv.Itoa(29))
urlB.RawQuery = values.Encode()
fmt.Printf("urlA: %s\n", urlA.String()) // This will be unchanged.
fmt.Printf("urlB: %s\n", urlB.String()) // This will have the new params.
Running this will print out:
urlA: https://example.com?name=alice&age=28&gender=female
urlB: https://example.com?age=29&name=alice&occupation=carpenter
As a side note, you can use this technique any time you want to 'clone' a URL and make changes to it. For example to create a clone of a URL with a different path, you can do this:
urlA, err := url.Parse("https://example.com/foo")
if err != nil {
log.Fatal(err)
}
urlB := *urlA
urlB.Path = "/bar"
fmt.Printf("%s\n", urlA.String()) // Prints https://example.com/foo
fmt.Printf("%s\n", urlB.String()) // Prints https://example.com/bar