Go Project Workspace Structure
In this page:
A Minimal Layout
The simplest possible Go project is just a go.mod file and a main.go in the same directory. As a project grows, code is split into subdirectories, each subdirectory becoming its own importable package named after its folder.
Example: A Minimal Layout
package main
import "fmt"
func main() {
fmt.Println("myapp/")
fmt.Println(" go.mod")
fmt.Println(" main.go")
}
Login to try C/C++/Java/PHP code in the editor
Organizing Packages by Folder
Each directory containing .go files (other than the root) typically represents one package, imported by its path relative to the module root, such as github.com/example/myapp/utils. This convention keeps related code together and makes the import graph easy to follow just by looking at the file tree.
Note: Package names are conventionally short, lowercase, and match the folder name.
Example: Organizing Packages by Folder
package main
import "fmt"
func main() {
layout := []string{"myapp/go.mod", "myapp/main.go", "myapp/utils/strings.go"}
for _, path := range layout {
fmt.Println(path)
}
}
Login to try C/C++/Java/PHP code in the editor
The internal/ Convention
Go treats any package inside a directory named internal specially: it can only be imported by code rooted at the parent of that internal directory. This is the standard way to mark packages as private implementation details that outside modules should not depend on.
Example: The internal/ Convention
package main
import "fmt"
func main() {
fmt.Println("myapp/internal/auth can only be imported from within myapp")
}
Login to try C/C++/Java/PHP code in the editor
Where Tests Live
Go test files sit right next to the code they cover and are named with a _test.go suffix, such as strings_test.go alongside strings.go. The 'go test' tool automatically finds and runs every _test.go file in a package, so there's no separate test-discovery configuration needed.
Example: Where Tests Live
package main
import "fmt"
func main() {
fmt.Println("utils/strings.go")
fmt.Println("utils/strings_test.go")
}
Login to try C/C++/Java/PHP code in the editor
- Putting all code in package main inside one giant file instead of splitting reusable logic into separate packages.
- Creating a top-level src folder out of old GOPATH habit, which modern Go modules don't require or expect.
- Mixing test files, main application code, and documentation with no consistent naming, making 'go build ./...' behave unpredictably.
- A typical Go project has a go.mod at its root and a main.go (or a cmd/ directory) as the entry point.
- Reusable logic is organized into small, focused packages, each in its own directory.
- The 'internal/' directory name has special meaning: it restricts imports to within the module.
- Test files live alongside the code they test, named with a _test.go suffix.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: