# Best Practices for Organizing Go Package Imports: A Complete Guide

> Master Go package import organization. Group standard library, third-party, and internal packages alphabetically for cleaner code and fewer merge conflicts.

- Repository: [golang-standards/project-layout](https://github.com/golang-standards/project-layout)
- Tags: best-practices
- Published: 2026-03-06

---

**Group Go imports into three distinct blocks—standard library, third-party modules, and internal project packages—sorted alphabetically within each group to minimize merge conflicts and improve code readability.**

The `golang-standards/project-layout` repository defines a battle-tested structure for Go applications that directly dictates how you should handle organizing Go package imports. Following these conventions ensures your codebase remains maintainable, enforces architectural boundaries, and aligns with the expectations of the Go toolchain.

## The Three-Zone Import Hierarchy

The project-layout standard divides code into three top-level directories that determine your import strategy:

- **`/pkg`** – Public libraries consumable by other projects. Import these using `github.com/yourorg/yourrepo/pkg/...`.
- **`/internal`** – Private code restricted to your module. The Go compiler enforces this boundary; imports must use `github.com/yourorg/yourrepo/internal/...`.
- **`/cmd`** – Small `main` packages that wire together public and private code. These typically import from both `/pkg` and `/internal`.

This separation forces a clear hierarchy in your import blocks, making dependencies immediately visible to reviewers and preventing accidental leakage of internal implementation details.

## Standard Import Grouping Rules

According to the `project-layout` main [`README.md`](https://github.com/golang-standards/project-layout/blob/main/README.md) (lines 39-44) and the official Go style guide, import statements must follow a strict three-group format separated by blank lines.

### Standard Library First

Begin with Go standard library packages such as `context`, `encoding/json`, `fmt`, and `net/http`. These represent your foundational dependencies with zero external cost and belong in the first block.

### Third-Party Dependencies Second

The second group contains external modules—any import path that does not start with your module prefix. For example, `github.com/gorilla/mux` or `go.uber.org/zap`. This isolates your external surface area and makes dependency auditing straightforward.

### Internal Packages Last

The final group contains your project's internal packages, identified by your module path prefix declared in `go.mod`. Examples include `github.com/golang-standards/project-layout/internal/app` and `github.com/golang-standards/project-layout/pkg/config`.

Within each group, **sort imports alphabetically**. This convention produces cleaner diffs and allows developers to locate dependencies instantly without scanning unordered lists.

## Enforcing Import Hygiene with Go Tools

Consistent organizing Go package imports requires tooling automation rather than manual review.

### Using go.mod for Module Resolution

The `go.mod` file at your repository root declares the canonical module name (e.g., `github.com/golang-standards/project-layout`). This identifier serves as the prefix for all internal imports, ensuring the compiler resolves them through the module cache rather than relative paths. Never use relative imports like `./foo` or `../bar`; always use the full module path to guarantee reproducible builds across different environments.

### Automated Formatting with goimports

Run `goimports` before committing code. This tool automatically rewrites import blocks to satisfy the three-group rule, adds missing imports, and removes unused ones. The [`cmd/README.md`](https://github.com/golang-standards/project-layout/blob/main/cmd/README.md) in the project-layout repository demonstrates how main packages should leverage this tooling to maintain clean wiring between `/pkg` and `/internal` packages without manual intervention.

## Practical Import Layout Example

Here is a complete example from a [`cmd/yourapp/main.go`](https://github.com/golang-standards/project-layout/blob/main/cmd/yourapp/main.go) file demonstrating the three-group pattern:

```go
package main

import (
	// Standard library
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"

	// Third‑party dependencies
	"github.com/gorilla/mux"
	"go.uber.org/zap"

	// Internal project packages
	"github.com/golang-standards/project-layout/internal/app"
	"github.com/golang-standards/project-layout/pkg/config"
)

func main() {
	logger := app.NewLogger()
	logger.Info("starting server")

	cfg := config.Load()
	r := mux.NewRouter()
	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Hello, world!")
	}).Methods(http.MethodGet)

	srv := &http.Server{
		Addr:    fmt.Sprintf(":%d", cfg.Port),
		Handler: r,
	}
	if err := srv.ListenAndServe(); err != nil {
		log.Fatalf("server failed: %v", err)
	}
}

```

Running `goimports -w main.go` validates this structure and fixes any deviations from the grouping or sorting rules.

## Summary

- **Use three import groups**: standard library, third-party modules, then internal packages, each separated by a blank line.
- **Sort alphabetically** within each group to reduce merge noise and improve scannability.
- **Avoid relative imports**; always use the full module path declared in `go.mod`.
- **Leverage `/pkg` for public APIs** and `/internal` for private implementation details to enforce boundaries.
- **Run `goimports`** automatically to enforce these rules without manual effort.

## Frequently Asked Questions

### Why does Go require grouping imports into three blocks?

The three-block structure separates concerns: standard library (stable, built-in), third-party (external dependencies with different maintenance cycles), and internal (your business logic). This separation makes dependency analysis faster and aligns with `go fmt` conventions referenced in the `project-layout` main [`README.md`](https://github.com/golang-standards/project-layout/blob/main/README.md) (lines 39-44).

### Can I use relative imports like `../internal/app` in my Go project?

No. Relative imports break when others import your module and violate the `project-layout` standards documented in [`internal/README.md`](https://github.com/golang-standards/project-layout/blob/main/internal/README.md). Always use the canonical module path defined in `go.mod`, such as `github.com/yourorg/yourrepo/internal/app`. The compiler resolves these through the module cache, ensuring reproducible builds.

### How do I prevent internal packages from being used by external projects?

Place private code in the `/internal` directory. The Go compiler enforces this restriction automatically—packages under `github.com/yourorg/yourrepo/internal/` can only be imported by code within the same module subtree. This mechanism is documented in [`internal/README.md`](https://github.com/golang-standards/project-layout/blob/main/internal/README.md) within the project-layout repository.

### Should I manually sort my imports or use a tool?

Always use `goimports`. This tool automatically groups imports into the standard three blocks, sorts them alphabetically, and manages missing or unused dependencies. Manual sorting is error-prone and unnecessary when `goimports` integrates seamlessly with editors and CI pipelines.