Today we’re looking at one of the more essoteric parts of the spec.
Import declarations
…
Implementation restriction: A compiler may restrict ImportPaths to non-empty strings using only characters belonging to Unicode’s L, M, N, P, and S general categories (the Graphic characters without spaces) and may also exclude the characters !"#$%&’()*,:;<=>?[]^`{|} and the Unicode replacement character U+FFFD.
Other than what’s stated in the quote, we’re not going to look at an exhaustive list of what is and isn’t guaranteed to be supported by a Go implementation. The point here is: Certain characters must be supported in an import path, and others may optionally be supported.
Why such confusion?
I can offer a guess: Diverse file systems.
I believe the authors wanted to allow an import path to map to a file path as closely as possible, on a wide variety of filesystems. But at the same time, they don’t want to require someone running Go on an old FAT filesystem (remember those 8.3 file names?) to support the 🔥 symbol in an import path/file name.
When we couple this implentation restriction with the earlier note that “[t]he interpretation of the ImportPath is implementation-dependent”, we’re left with a lot of flexibility, but also a guideline that import paths generally should map to filepaths.
How should this impact you?
Try not to put wild and interesting characters in your path names, and everything should work nicely. Just because your local development environment (operating system, file system, and Go implementation) lets you create a package at github.com/fire/breathers/🔥
, and you can successfully import it:
import "github.com/fire/breathers/🔥"
doesn’t mean you can count on it working for other consumers of your package.
Quotes from The Go Programming Language Specification Language version go1.23 (June 13, 2024)