This is a creation in Article, where the information may have evolved or changed.
Go ' s PackageName Space
Posted Ontuesday, February 2, 2010.
GO organizes programs into individualpieces called packages. A package gets to pick a short name for Itself,like vector, even if the import statement must use a longer pathlike "Container/vector" to name the file where the compiled Codeis installed. The early Go compilers used the package name as a uniqueidentifier during linking, so That vector ' S new fun Ction could be distinguished fromlist ' s new. In the final binary, one was vector. New and the other list. New. As we started to fill out the standardlibrary, it became clear that we needed to does something about managing Thepackage NA Me space:if multiple packages tried to being package vector, their symbols would collide in Thelinker. For a while we considered segmenting the name space, reservinglower-case names for standard packages and upper-case names For local packages. (Since package Names and object file names be conventionally the same, Onereason not to does this is the IT WouLD require a case-sensitive file system.)
other languages simply use longer names. Both Java and Python tie the name to the directory in which the package isfound, as in com.java.google.webserver ; for the code incom/java/google/webserver.class. In practice the leads to unnecessarilylong identifiers, and something Go tries to avoid. It also ties the name to aparticular mechanism for finding code:a file system. One of the reasons Thatimport paths is a string constants in Go was so it's easy-to-substituteother notations, like UR Ls.
last Spring, during a long discussionabout how to divide up the package name space, Robert Griesemer cut T He gordianknot by suggesting, we allow multiple packages to choose Asingle name and fix The tool chain to cope. the import statement already allows introducing a localalias for the package during the import, So there ' s no linguistic reason packagenames has to be unique. We all agreed the is the right approach, but Weweren ' t sure how to implement it. Other considerations, like the open Sourcerelease, took-during most of the above, but we recently returned to Theprobl Em. (translation: Last spring, we had a long discussion about how to divide the namespace of the package, and finally Robert Griesemer the Gordian Knot: we allow multiple packages to use the same name, and modify the Go compiler tool chain to accommodate this decision.) The import statement allows an alias to be defined when the package is introduced. So no language level restrictions the package name must be unique. We think this is the right path, but we are not sure we can achieve it. Consider other factors: such as the 2009 open source release as a priority event, but we return to solve this problem. )
Package Reference Format:
Import "Lib/math"//Math. Sin Normal Application
Import M "Lib/math"///M.sin uses aliases to avoid the introduction of packages with the same package name to cause conflicts
Import. "Lib/math" Sin omits the swap prefix, directly using the functions and variables in the package
Import _ "Lib/math"//_ operation is actually to introduce the package, instead of directly using the function inside the package, instead of calling the INIT function inside the package.
Go Support initialization function :
• Each source ⽂ file can define one or more initialization functions, func init () {}.
• All initialization functions will be ⽤ on a single thread prior to main () and executed only once.
• The compiler does not guarantee the order of execution of multiple initialization functions.
• The initialization function ⾏ rows after all global variable initialization (0 or initialization expression values) of the current package is complete.
• You cannot directly or indirectly ⽤ the initialization function in your program code.
Ultimately, the linker needs some uniquename for each symbol in the program; The fundamental problem caused by Decidingthat package names won ' t being unique is to find another source of uniqueness THATF it into the tool chain well.
The best approach* seems to is to use Thepackage ' s import path as the unique identifier, since it must uniquely Identifyth E package in the import statement already. Then Container/vector ' s New iscontainer/vector. New. but! When would you ' re compiling a package,how does the compiler know what's the package ' s import path would be? The packagestatement just says Vector, and while every compilation Thatimports "Container/vector" knows the import path, t Hecompilation of vector itself does not, because compilation was handledseparately from installing the binary in its final, Importable location.
Last week I changed the GC compiler Suiteto does this. My solution to the import path question is to introduce a specialname syntax that refers to "this package ' s import path." Because the importpaths is string literals in the Go compiler metadata, I chose the emptystring-""-as the Self-reference Name. Thus, the object file for package vector, the local symbol New is written "". New. When the linker reads the object file,it knows what import path it used to find the file. It substitutes that pathfor the "", producing, in this case, the unique name Container/vector. New.
Not embedding a package's final installedlocation in it object file makes the object files easy to move and duplicate. For example, consider this trivial package:
Package seq
var n int
Func Next () int {
n++
return n
}
It ' s valid for a Go program to import thesame path multiple times using different local names, but all the names end Upref erring to the same package:
Package Main
Import (
"FMT"
S "seq"//Changed to "SEQ1" later
T "seq"
)
Func Main () {
Fmt. Println (S.next (), S.next (), T.next (), T.next ())
}
Prints 1 2 3 4, because it all four calls is to thesame Next function:
$6g Seq.go
$6g-i. Main.go
$6l-l. main.6
$6.out
1 2 3 4
$
If we change one of the imports Tosay "seq1" and then merely copy the "seq" Binary to "seq1", we ve created a distinct Package, usinglowly CP instead of a compiler:
$ CP seq.6 seq1.6
$ ed Main.go
120
/seq
S "Seq"
S/seq/seq1
S "seq1"
Wq
121
$6g-i. Main.go
$6l-l. main.6
$6.out
1 2 1 2
$
Now the S.next calls refer to seq1.6 's next, while the T.next calls refer to seq.6 ' s next. Duplicating the object actuallyduplicated the code. This was very different from the behavior of a TRADITIONALC compiler and linker.
A digression:the Explicit "". Prefix is not strictly necessary. Itwould is cleaner if the linker treated every symbol as needing to being Qualifiedby the import path, so and all the "". Could be dropped. But Occasionallyit's important to being able to break the rules, for example to define a symbolthat are logically in one packa GE is implemented in another. For example, theimplementation of unsafe. Reflectis actually in the binary for package runtime, because that's where all the Interfacemanipul ation Code lives:
$6nm Pkg/darwin_amd64/runtime.a|grepreflect
Iface.6:t unsafe. Reflect
$
another reason to use a explicit prefixis to admit names with no prefix @ All, as would is generated by Legacy Ccode. Otherwise, what is should C ' s printf be in? IF the linker enforced astrict boundary between packages, both of these examples would be impossible. Most of the time is would a good thing, but systems languages does not havethe luxury of stopping for "most of the time." "Last October, a few weeks beforethe public release of Go, I changed the linker to insert import path Qualifierson all NA Mes during linking, but it is too disruptive a change to commitbefore the release. Last week's implementation, which allows for semipermeablepackage boundaries, was a much better fit for Go.
This week Ian Lance Taylor was working oneliminating the global package name space assumption in Gccgo. He ' d like toavoid making changes to the linker, which rules out introducing a "thispackage" notation like "". Gccgo must be able to write objects thatknow their own import paths, which means gccgo must know the import path atcompile Time. But how? There would be a new GCCGO command line option, and Thebuild system would simply tell the compiler what the import path is.
In retrospect, I wonder if the Effortof ' "in the GC tool chain is justified compared toadding an option. The GC implementation is easier to use, but it's not clearhow important that'll be. Time would tell.