Go Module Package Import
2026-10-05
Let's explain how Go import works with the following project.
Folder structure:
demo
├── animal
│ └── pet.go
├── go.mod
└── main.go
go.mod:
module zoo
go 1.25.9
main.go:
package main
import "zoo/animal"
func main() {
dog.Bark()
}
pet.go:
package dog
import "fmt"
func Bark() {
fmt.Println("Bark!")
}
We have three files (go.mod, main.go, pet.go) in two folders (demo, animal) making up one module (zoo) and one package (dog).
The module name is "zoo" as defined in the module statement in go.mod. You can name your module anything you like. However, if you prefix the module name with a github repo name, Go will look for it at that repo if it cannot find the module locally.
The package name is "dog" as defined in the package statement in pet.go. The filename pet.go has nothing to do with the package name. You can name the file anything you like. All the files in the same folder must belong to the same package though. That means one package per folder.
The name of the containing folder (animal) has nothing to do with the package name too. However, best practice is to name it the same as the package name (in this case: dog instead of animal).
The name of the containing folder is significant though when the package is being imported. In main.go, we import the package by specifying the module name and the package path (i.e. zoo/animal). The package name is not even in the import statement. Go will figure out the package name from the package statement in the source file(s) in the specified path. That is why we can call dog.Bark() in main.go although "dog" is not mentioned anywhere in the import statement.
Please note that the naming convention in this project is not Go best practice but contrived for illustration purpose.