Hackerman's Hacking Tutorials

The knowledge of anything, since all things have causes, is not acquired or complete unless it is known by its causes. - Avicenna

Mar 9, 2019 - 2 minute read - Comments - Go

path.Join Considered Harmful

Credit goes to my friend Stark Riedesel. Check out his github profile. One of these days I will bully him into reviving his blog.

TL;DR: Instead of path.join use filepath.Join.

What's Wrong with path.Join?

path.Join joins a bunch of paths together. Problem is, it uses / as separator regardless of operating system. We can see it in its source at https://golang.org/src/path/path.go?s=4034:4066#L145:

func Join(elem ...string) string {
	for i, e := range elem {
		if e != "" {
			return Clean(strings.Join(elem[i:], "/")) // <---
		}
	}
	return ""
}

This is problematic on Windows where your paths (or some of them) use \ as separators. Consider this minimal example Go playground link:

package main

import (
	"fmt"
	"path"
)

func main() {
	// Create the path to the hosts file.
	path1 := "c:\\windows\\system32"
	path2 := "drivers\\etc\\hosts"

	fmt.Println(path.Join(path1, path2))
}

You would expect it to create the correct path. Instead, you get:

  • c:\windows\system32/drivers\etc\hosts

What Should We Use Instead?

Use filepath.Join instead. It uses OS specific separators.

Note 1: If you modify the example on the playground to filepath.Join you still get the same result. Obviously, Go playground is not running on Windows.

Note 2: Alternatively, you could convert all paths to use / as the separator. c:/windows/system32/drivers/etc/hosts is an acceptable Windows path. This is what I did in borrowed time after Stark told me about this issue.