Skip to content
Go Basics: Build URL Queries Without String Concatenation

Go Basics: Build URL Queries Without String Concatenation

October 31, 2026

Joining raw search terms into a URL can turn part of the value into a new parameter. Let net/url encode each value, including repeated keys, and inspect the round trip.

Prepare a scratch directory

Tested on Linux amd64 with Go 1.26.10. Install Go and make go available on PATH. You also need Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. The example uses only the standard library and needs no module or external dependency.

Keep the same terminal open. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as url-query-values-demo.go:

package main

import (
	"fmt"
	"net/url"
)

func main() {
	target, err := url.Parse("https://example.com/search?lang=en")
	if err != nil {
		panic(err)
	}
	query := target.Query()
	query.Set("q", "tea & cake")
	query.Add("tag", "go")
	query.Add("tag", "cli")
	target.RawQuery = query.Encode()
	fmt.Println("URL:", target.String())
	parsed, err := url.ParseQuery(target.RawQuery)
	if err != nil {
		panic(err)
	}
	fmt.Println("Search:", parsed.Get("q"))
	fmt.Println("Tags:", parsed["tag"])
}

Run it:

go run url-query-values-demo.go

Observed output:

URL: https://example.com/search?lang=en&q=tea+%26+cake&tag=go&tag=cli
Search: tea & cake
Tags: [go cli]

Read the result

Encode sorts parameter keys and escapes characters with query-specific rules. Set replaces all values for a key, while Add appends another value. Reading the slice retrieves both tags; Get would return only the first. This example manipulates an address in memory and makes no request.

Apply it carefully

Encoding is not destination validation. If an untrusted party supplies the base URL, separately restrict scheme, host, redirects, and network access. Query escaping also differs from path escaping: use the API suited to the component you are constructing.

The official Go reference documents the behavior used here.

Clean up

Remove the saved source, return to the starting directory, and remove the empty practice directory. go run does not leave an executable here; Go manages its build cache separately.

rm -- url-query-values-demo.go
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect its remaining contents before removing anything else.

Acknowledgements

This post was created with assistance from AI.

Last updated on