Golang: Import Module from Sub Directory
In Golang, importing modules is easy, however it has some opinions on how to structure your project. You're not supposed to sort the files of your project into different directories, but to keep your files in the root folder of your repository OR split out functionality into other modules.
However, it's not a cop, so you can still use the package
field and an import path to import modules from a sub-directory.
Go Idiomatic Directory Example
Let's create an ice cream shop that makes use of an icecream.go
model and some basic price calculation.
main.go
package main
import (
"fmt"
)
func main() {
myIcecream := Icecream{Flavour: "vanilla", Scoops: 3, BasePrice: 2.99}
fmt.Println(myIcecream.Price())
}
icecream.go
package main
type Icecream struct {
Flavour string
Scoops int
BasePrice float32
}
func (i Icecream) Price() float32 {
return i.BasePrice * float32(i.Scoops)
}
directory structure:
.
├── main.go
└── icecream.go
1 directory, 2 files
We can confirm that this works by running go run main.go icecream.go
and it should print: 8.97
.
Importing Go Files from Sub-directory Example
If we should decide to structure our projects with sub-directories, we need to make some changes. First of all, we should make sure to have a go.mod
file that states the name of our package, so let's run go mod init
, which will by defautl take the name of the directory as the module name.
go.mod
module icecream-shop
go 1.23.1
Next we can create a directory, like models
and move our icecream.go
file there.
directory structure:
.
├── go.mod
├── main.go
└── models
└── icecream.go
2 directories, 3 files
If we try to run our code with go run .
now, we'll get the following error:
# icecream-shop
./main.go:8:16: undefined: Icecream
Alright, let's now try to import it, we need to remember that unlike in for example JavaScript, we don't import specific files but modules, which are directories:
main.go
package main
import (
"fmt"
"icecream-shop/models"
)
func main() {
myIcecream := models.Icecream{Flavour: "vanilla", Scoops: 3, BasePrice: 2.99}
fmt.Println(myIcecream.Price())
}
Note:
- add
"icecream-shop/models"
- change
Icecream
tomodels.Icecream
However, we get another error if we try to execute it with go run .
:
main.go:5:2: import "icecream-shop/models" is a program, not an importable package
Lastly, we'll need to change the package name of the file we moved into the sub-directory, otherwise we'll not be able to import it and use it:
icecream.go
package models
type Icecream struct {
Flavour string
Scoops int
BasePrice float32
}
func (i Icecream) Price() float32 {
return i.BasePrice * float32(i.Scoops)
}
Note:
- we changed
package main
topackage models
, signalling that this is its own module
Summary
If you're structuring your project, evaluate carefully if the functionality you're moving around should in fact be its own package or repository.
If not, remember to use the correct import paths.