Question

Fix Go "Cannot Find Package" Errors: GOPATH and Package Layout

gobuildpackage

Question

Even though GOPATH is set correctly, why can go build and go run not find my own package? What is wrong with this project layout?

$ echo $GOROOT
/usr/local/go

$ echo $GOPATH
/home/mitchell/go

$ cat ~/main.go
package main

import "foobar"

func main() {}

$ cat /home/mitchell/go/src/foobar.go
package foobar

$ go build main.go
main.go:3:8: import "foobar": cannot find package

Short Answer

Go does not search every .go file directly inside GOPATH/src. In GOPATH mode, an import path such as "foobar" maps to a directory: $GOPATH/src/foobar. You will learn the required layout, why the error occurs, and how to use Go modules for new projects.

Concept

An import in Go names a package path, not a particular Go file.

In the example:

import "foobar"

When using legacy GOPATH mode, Go looks for the package source in this directory:

/home/mitchell/go/src/foobar

It then compiles the Go files in that directory that declare:

package foobar

However, the source file is currently here:

/home/mitchell/go/src/foobar.go

That is a file alongside the workspace's src contents, not a package directory named foobar. Therefore, Go cannot resolve the import path.

The GOPATH workspace convention is:

$GOPATH/
├── src/       source packages
├── pkg/       compiled package cache (legacy)
└── bin/       installed executable commands

For new Go code, use Go modules instead of organizing projects around GOPATH. Modules explicitly define a project's import path and dependencies in a go.mod file. GOPATH is still used by Go for caches and installed tools, but it is no longer the normal place to put project source code.

Mental Model

Think of an import path as a mailing address for a folder.

If you write:

import "foobar"

Go addresses the package to the foobar folder inside its source root. It expects to find a building at this address:

$GOPATH/src/foobar/

Placing a file named foobar.go directly in $GOPATH/src is like writing a person's name on an envelope but leaving out their street address. The names look related, but Go needs the matching directory structure to locate the package.

Take Quiz

Syntax and Examples

In legacy GOPATH mode, a package import path maps to a directory below $GOPATH/src.

$GOPATH/src/<import-path>/*.go

For import "foobar", use this structure:

/home/mitchell/go/
└── src/
    ├── foobar/
    │   └── foobar.go
    └── myapp/
        └── main.go

/home/mitchell/go/src/foobar/foobar.go:

package foobar

func Message() string {
	return "Hello from foobar"
}

/home/mitchell/go/src/myapp/main.go:

package main

import (
	"fmt"
	"foobar"
)

func main() {
	fmt.Println(foobar.Message())
}

Run the application from its directory:

cd /home/mitchell/go/src/myapp
go run .

The package directory is named foobar because that is the import path. The Go file inside it can have another filename, such as message.go; filenames do not determine the import path.

Step by Step Execution

Consider this legacy GOPATH-mode import:

import "foobar"

Go resolves it as follows:

  1. It reads GOPATH:

    /home/mitchell/go
    
  2. It adds src/ because source packages are stored below $GOPATH/src.

    /home/mitchell/go/src
    
  3. It appends the import path, foobar.

    /home/mitchell/go/src/foobar
    
  4. It searches that directory for buildable .go files whose package declaration is package foobar.

  5. In the original layout, only this file exists:

    /home/mitchell/go/src/foobar.go
    

    This is not inside /home/mitchell/go/src/foobar, so the package lookup fails.

  6. Moving the file to this location makes the import resolvable:

    /home/mitchell/go/src/foobar/foobar.go
    

For a modern module project, Go instead begins import resolution with the current module's go.mod file and its declared module path.

Real World Use Cases

Package paths and directory layout matter whenever one Go package uses another:

  • Application layers: A main package imports internal code such as example.com/shop/internal/orders.
  • Reusable libraries: A package such as example.com/company/logging exposes shared logging helpers.
  • API services: A server command imports packages for routing, database access, and request validation.
  • Command-line tools: A cmd/tool command imports business logic from a separate package.
  • Multi-package repositories: A project may keep related packages in directories such as config, storage, and service.

In all cases, Go identifies a package by its import path and directory, rather than by a single filename.

Take Quiz

Real Codebase Usage

Modern Go projects usually use modules and keep commands separate from reusable packages.

Example layout:

weather-cli/
├── go.mod
├── cmd/
│   └── weather/
│       └── main.go
└── internal/
    └── forecast/
        └── forecast.go

go.mod might declare:

module example.com/acme/weather-cli

Then main.go can import the local package with its module-based path:

import "example.com/acme/weather-cli/internal/forecast"

Common project patterns include:

  • Commands in cmd/: Each subdirectory is usually one executable program.
  • Internal packages: Put implementation details in internal/ to prevent unrelated modules from importing them.
  • Small focused packages: Group files by responsibility, not by file extension or class-like types.
  • Explicit dependencies: Record third-party dependencies in go.mod and go.sum.
  • Package-level tests: Keep *_test.go files alongside the package they test.

Avoid manually copying dependency source into GOPATH for new projects. Use go mod init, go get, and go mod tidy instead.

Common Mistakes

Putting a package file directly in GOPATH/src

This does not create the foobar import path:

$GOPATH/src/foobar.go

Use a directory:

$GOPATH/src/foobar/foobar.go

Assuming the filename controls the import path

This is valid:

$GOPATH/src/foobar/message.go

as long as message.go contains:

package foobar

The folder determines the import path; the filename does not.

Mixing packages in one directory

Non-test Go files in the same directory generally must use one package name.

Broken example:

// first.go
package foobar

// second.go
package main

Avoid putting executable package main code and reusable package foobar code in the same folder.

Using GOPATH layout for a new module project

Modern Go defaults to module-aware behavior. Create a module instead:

go mod init example.com/yourname/myapp

Then use imports beginning with that module path.

Confusing GOROOT with GOPATH

  • GOROOT identifies the Go installation and standard library location.
  • GOPATH was the legacy workspace root and is now mainly used for caches and installed binaries.

Changing GOROOT does not fix an incorrectly placed application package.

Importing a package but never using it

After Go finds a package, this can still fail:

import "foobar"

func main() {}

Go rejects unused imports. Use an exported identifier, such as foobar.Message(), or remove the import.

Comparisons

TopicGOPATH modeGo modules
Project locationNormally under $GOPATH/srcCan be in almost any directory
Local import pathDerived from directory below srcDerived from the module line in go.mod
Dependency trackingHistorically stored in workspace directoriesRecorded in go.mod and checksums in go.sum
Recommended for new projectsNoYes
ItemDetermines itExample
Import pathModule path plus package directory, or GOPATH src directory in legacy modeexample.com/acme/app/config
Package nameThe package declarationpackage config
Go filenameChosen by the developerconfig.go

A package name often matches its final directory name, but it is the import path and directory layout that let Go find the package.

Take Quiz

Cheat Sheet

Legacy GOPATH lookup:
import "name"  ->  $GOPATH/src/name/
import "a/b"   ->  $GOPATH/src/a/b/
Correct GOPATH package layout:
$GOPATH/src/foobar/foobar.go
// foobar.go
package foobar

func Message() string { return "hello" }
// main.go
package main

import (
	"fmt"
	"foobar"
)

func main() {
	fmt.Println(foobar.Message())
}
# Modern project setup
go mod init example.com/yourname/project
go run .
go mod tidy

Rules to remember:

  • Imports identify packages, not individual .go files.
  • A package is a directory containing Go source files.
  • Files in one directory generally share one package declaration.
  • GOROOT is the Go installation; it is not your project workspace.
  • Prefer Go modules for new code.

FAQ

Why does Go look for a directory rather than foobar.go?

A package can contain multiple Go files. Go compiles the package directory as a unit, so imports refer to directories rather than filenames.

What exact folder should import "foobar" use in GOPATH mode?

Place Go source files for that package in $GOPATH/src/foobar/, for example $GOPATH/src/foobar/foobar.go.

Does the Go filename have to match the package name?

No. message.go, client.go, and helpers.go may all declare package foobar in the same foobar directory.

Should I still put projects inside GOPATH?

Usually no. New projects should use Go modules, which let you work outside GOPATH and manage dependencies with go.mod.

How do I start a Go module?

From the project root, run:

go mod init example.com/yourname/project

Use a module path appropriate for where the code will live, especially if it will be published.

Why does Go report an unused import after it finds my package?

Go requires every import to be used in the file. Call an exported function, reference an exported type, or remove the import.

Can package main import another package main?

No. Put reusable code in a non-main package. A main package is intended to build an executable command.

Take Quiz

Mini Project

Description

Build a small Go module with a command package and a reusable greeting package. This demonstrates the modern equivalent of organizing code into importable package directories, without requiring the project to be inside GOPATH.

Goal

Create and run a command that imports a local package using the module path declared in go.mod.

Requirements

Create a project directory containing a go.mod file.

Declare the module path as example.com/greeter.

Create a greeting package in its own directory with a function that returns a greeting.

Create a main package that imports example.com/greeter/greeting.

Run the application with go run . from the project root.

Take Quiz

Keep learning

Related questions

View more