Every Go file starts with package <something>
.
As far as I understand - and this is probably where I am missing some information - there are only two possible values for <something>
: The name of the directory it is in*, or main
. If it is main
, all other files in that directory can only have main
, too. If it is something else, the project is inconsistent/violating convention.
Now if it is the name of the directory, it's redundant, because the same information is, well, in the name of the directory.
If it is main
, it's kind of useless, because as far as I can see there is no way to tell go build
to "please build all main
packages".
* Because, in other words, one directory is one package.
A package is a schema object that groups logically related PL/SQL types, items, and subprograms. Use packages when writing a set of related subprograms that form an application programming interface (API) that you or others might reuse.
A package consists of package declaration (mandatory) and may contain a single optional package body. The purpose of a package is to declare shareable types, subtypes, constants, signals, files, aliases, component, attributes and groups. Once a package is defined, it can be used in multiple independent designs.
The package is a unit that groups various declarations, which can be shared among several designs. Packages are stored in libraries. A package is split into a package declaration (mandatory) and a package body (optional).
The name of the package does not have to coincide with the directory name. It is possible to have package foobar
in the directory xyz/go-foobar
. In this case, xyz/go-foobar
becomes an import path, but the package name that you use to quality the identifiers (functions, types etc.) would be foobar
.
Here's an example to make it more concrete: I created a test package http://godoc.org/github.com/dmitris/go-foobar (source in https://github.com/dmitris/go-foobar) - you can see from the documentation page, that the import path is "github.com/dmitris/go-foobar" but the package name is foobar
, so you would call the function it provides as foobar.Demo()
(not go-foobar.Demo()
).
A similar real-life example - the import path for the NSQ Messaging platform is "github.com/nsqio/go-nsq" while the package name is "nsq": http://godoc.org/github.com/nsqio/go-nsq. However, for the sake of user-friendliness and simplicity, the standard and recommended practice is to keep the last portions of the import path and the package name being the same whenever possible.
package main
is not useless - it tells the Go compiler to create an executable as opposed to a .a library file (with go install
or go get
; go build
discards the compilation result). The executable is named after the directory name in which the package main
file or files are placed. Again a concrete example - I made a test program https://github.com/dmitris/go-foobar-client, you install it with go get github.com/dmitris/go-foobar-client
and you should get a go-foobar-client
executable placed in your $GOPATH/bin directory. It is from the the directory name where the package main
file is placed that the Go compiler takes the name of the executable from. The filename of the .go
file that contains the main()
function is not important - in the example above, we can rename main.go
to client.go
or something else, but as long as the enclosing directory is called go-foobar-client
, that's how the resulting executable will be named.
For an additional accessible and practically oriented reading about Go packages, I recommend Dave Cheney's article "Five suggestions for setting up a Go project" http://dave.cheney.net/2014/12/01/five-suggestions-for-setting-up-a-go-project.
The missing information you "have" is that the package name does not need to be the same as the directory name.
It is perfectly fine to use a package name other than the folder name. If you do so, you still have to import the package based on the directory structure, but after the import you have to refer to it by the name you used in the package clause.
For example, if you have a folder $GOPATH/src/mypck
, and in it you have a file a.go
:
package apple
const Pi = 3.14
Using this package:
package main
import (
"mypck"
"fmt"
)
func main() {
fmt.Println(apple.Pi)
}
Just like you are allowed to use relative imports but is not advisable, you may use package names other that their containing folder, but this is not advisable also to avoid further misunderstanding.
Note that the specification doesn't even require all files belonging to the same package to be in the same folder (but it may be an implementation requirement). Spec: Package clause:
A set of files sharing the same PackageName form the implementation of a package. An implementation may require that all source files for a package inhabit the same directory.
Simple. A package name is a Go identifier:
identifier = letter { letter | unicode_digit } .
Which allows unicode letters to be used in identifiers, e.g. αβ
is a valid identifier in Go. Folder and file names are not handled by Go but by the Operating System, and different file systems have different restrictions. There are actually many file systems which would not allow all valid Go identifiers as folder names, so you would not be able to name your packages what otherwise the language spec would allow.
So in one hand not all valid Go identifiers may be valid folder names. And on the other hand, not all valid folder names are valid Go identifiers, for example go-math
is a valid folder name in most (all?) file systems, but it's not a valid Go identifier (as identifiers cannot contain the dash -
character).
Having the option to use package names different than their containing folders, you have the option to really name your packages what the language spec allows, regardless of the underlying operating and file system, and put it in a folder named anything that the underlying OS and file system allows - regardless of the package name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With