In web development, a common task is to combine different URL elements into one, for example, if you are developing a REST API client and want to concatenate a given hostname with relative paths to endpoints. In Go since version 1.19 this is very easy, just use the url.JoinPath()
function from the net/url
package. Alternatively, you can also use the JoinPath()
method of the URL
struct from the same package.
These functions can help you avoid common errors that can arise when manually concatenating path elements, for example, double slashes or missing slashes in the final URL, which can cause unexpected behavior.
Examples
The basic use of the url.JoinPath()
function is straightforward. You simply pass the base URL as the first argument, and pass further elements of the URL you want to join to the base one as subsequent arguments. The signature of the function looks as follows:
func JoinPath(base string, elem ...string) (result string, err error)
The url.JoinPath()
function automatically takes care of the correct formatting of the resulting URL, ensuring that it is well-formatted without redundant /
or ../
characters.
Take a look at the example below to see how it works:
package main
import (
"fmt"
"log"
"net/url"
)
func main() {
hostname := "https://gosamples.dev/"
path1 := "//join-url-elements//"
path2 := "/foo/"
path3 := "//bar"
result, err := url.JoinPath(hostname, path1, path2, path3)
if err != nil {
log.Fatal(err)
}
fmt.Println(result)
}
In the output you will get the resulting URL cleaned of redundant elements as a string
:
https://gosamples.dev/join-url-elements/foo/bar
Alternatively, if you have a URL as a url.URL
type and also want to get a url.URL
structure as a result, you can use the JoinPath()
method, passing as arguments only the new elements you want to join to the existing URL. The method works exactly the same as the url.JoinPath()
function from the previous example:
package main
import (
"fmt"
"log"
"net/url"
)
func main() {
gosamplesURL, err := url.Parse("https://gosamples.dev/")
if err != nil {
log.Fatal(err)
}
path1 := "//join-url-elements//"
path2 := "/foo/"
path3 := "//bar"
newGosamplesURL := gosamplesURL.JoinPath(path1, path2, path3)
if err != nil {
log.Fatal(err)
}
fmt.Println(newGosamplesURL)
}
In the output, you will get the resulting URL cleaned of unnecessary elements as a url.URL
struct:
https://gosamples.dev/join-url-elements/foo/bar
And that’s it. Happy coding! ๐จโ๐ปโจ๐