Packages - Introduction
Every Go program is made up of packages.
Note: Do not get confused with Go modules, which is Go’s dependency management system. A Go modules usually contains one or more Go packages. We will discuss Go modules later, for now, just remember that we are talking about packages and just pretend modules don’t exist.
Programs start running in package main
.
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println("My favorite number is", rand.Intn(10))
}
Use package
at the beginning of the code to specify the current package.
Use import
to import other packages.
Import
import
can take the following two styles:
import (
"fmt"
"math/rand"
)
代码语言:javascript复制import "fmt"
import "math/rand"
The prior grouped style is the recommeded “good” style by Go.
Exported names and non-exported names
In Go packages, only exported names can be accessed outside the same package.
A name is exported if it begins with a capital letter.
Examples:
Pizza
is an exported name since it starts with capital letterP
Pi
starts with a capital letter thus is an exported name from packagemath
. (Accessible withmath.Pi
)Println
is an exported name of packagefmt
Foobar
will be an exported name if you ever use it in your package.foobar
however, will NOT be exported if you use it in your package. It’ll be “unexported” thus inaccessable from outside the package.
By designing the language this way, Go effectively forced you to name your functions and types using a standard and preselected naming style. (“CamelCase” for exported names, “lower camelCase” for internal unexported names)
Whether that’s a good thing or a bad thing is up for debate, but this design decision ditched the need of the keyword
public
,export
orextern
commonly found in other languages, making programmers’ lives easier. It also makes the naming in all packages more unified and predictable, which is a good thing.
Package Scope
There’s no “global” scope in Go, instead, all functions and variables that is not local is in the package scope.
代码语言:javascript复制package myPackage
var v1, v2, v3 int // in package scope 'myPackage'
var Var1 int // in package scope 'myPackage', exported
func myfunction() int {} // also in package scope 'myPackage'
func AnotherFunc() int {} // in package scope 'myPackage', but it's also "exported" so
// it is accessible outside of package 'myPackage' by using
// `myPackage.AnotherFunc()`
Functions and variables within package scope is accessible within the whole package. Whether a name is accessible from outside the package however, is determined by the naming style of the name. See Exported names and non-exported names.
In this case, AnotherFunc()
can be accessed in another package like this:
package main
import (
"fmt"
"path/to/myPackage" // we will talk about this later
)
func main() {
myPackage.AnotherFunc() // works
fmt.Println(myPackage.Var1) // works
// myPackage.myFunction() // this doesn't work since `myFunction` is not exported
}
This is just for showcasing the difference between exported names and non-exported names, as well as the idea that you can access functions and variables in other packages.
Conclusion
We’ll be covering more about packages in a future article. For now, knowing how to use packages is enough.