Question
I am trying to create and use a custom package in Go. I currently have these two files in the same directory:
// mylib.go
package mylib
type SomeType struct{}
// main.go
package main
import "mylib"
func main() {}
When I run:
go run main.go
I receive this error:
main.go:4:2: package mylib is not in std (/usr/local/go/src/mylib)
I also tried running go build mylib.go, but it did not generate a file or show an error. How should I organize and import a custom Go package correctly?
Short Answer
You will learn that a Go package is normally a directory of .go files, that one directory cannot contain both package main and package mylib, and that imports are resolved through a module path. You will also learn why building a library package usually does not produce an executable file.
Concept
In Go, packages organize code, and modules define import paths and dependency boundaries.
The key rule is:
All non-test Go source files in one directory must declare the same package name.
Therefore, main.go cannot use package main while mylib.go in that same folder uses package mylib. Put reusable package code in its own subdirectory.
Modern Go projects use a go.mod file to declare a module. The module name becomes the beginning of the import path for packages inside that project.
For example, if your module is named example.com/myapp and your library is in a mylib folder, import it with:
import "example.com/myapp/mylib"
A package does not need to be publicly hosted just because its module path looks like a URL. During local development, Go resolves that path using the current module's go.mod file.
Also, go build behaves differently depending on the package:
- Building
package maincan create an executable program. - Building a normal library package checks and compiles it for use by other code, but it usually does not leave a standalone binary in the directory.
Mental Model
Think of a Go module as a building, and each package as a room inside it.
- The
go.modfile is the building's address. - Each folder is a room.
- The Go files in one room must all have the same room label: the same
packagedeclaration. - An import path is the address used to visit another room.
Your application entry point belongs in the main room. Reusable code belongs in another room, such as mylib. You cannot put both room labels on files in the same room (directory).
Syntax and Examples
Create a module first:
go mod init example.com/myapp
Organize the project like this:
myapp/
├── go.mod
├── main.go
└── mylib/
└── mylib.go
go.mod:
module example.com/myapp
go 1.22
mylib/mylib.go:
package mylib
type SomeType struct {
Name string
}
func NewSomeType(name string) SomeType {
return SomeType{Name: name}
}
main.go:
package main
import (
"fmt"
"example.com/myapp/mylib"
)
func main() {
value := mylib.NewSomeType("Ada")
fmt.Println(value.Name)
}
Run the whole program from the module root:
go run .
The output is:
Ada
Names beginning with an uppercase letter, such as SomeType and NewSomeType, are exported and can be used from another package. Lowercase names are package-private.
Step by Step Execution
Consider this program structure:
// mylib/mylib.go
package mylib
func Greeting(name string) string {
return "Hello, " + name
}
// main.go
package main
import (
"fmt"
"example.com/myapp/mylib"
)
func main() {
message := mylib.Greeting("Sam")
fmt.Println(message)
}
When you run go run ., Go performs these steps:
- It reads
go.modand finds the module path:example.com/myapp. - It loads the root package, which is
package main. - It sees the import
example.com/myapp/mylib. - It maps that import path to the local
mylibdirectory inside the module. - It compiles the
mylibpackage. - It compiles
main, which callsmylib.Greeting("Sam"). Greetingreturns"Hello, Sam".fmt.Printlnprints the returned string.
Output:
Hello, Sam
Real World Use Cases
Custom packages help keep real Go applications organized.
- HTTP applications: Put request handlers in
internal/httpapiorhandlers. - Database access: Keep queries and repository code in a
storeordatabasepackage. - Business rules: Place pricing, permissions, or order logic in a
servicepackage. - Reusable utilities: Put focused helpers, such as date formatting or validation, in a small package.
- Command-line tools: Keep
package mainsmall and place command logic in separate packages. - Shared types: Define domain types such as
User,Order, orInvoicenear the package that owns their behavior.
The purpose is not to create many tiny folders immediately. Create a package when code has a clear responsibility and is useful as a group.
Real Codebase Usage
In production Go code, the main package is commonly small. It wires together configuration, dependencies, and the application entry point.
For example:
myapp/
├── go.mod
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ ├── config/
│ ├── service/
│ └── store/
└── pkg/
└── validator/
Common package patterns include:
cmd/: executable entry points. Each command contains apackage main.internal/: application code that can only be imported by code within the parent project tree. This prevents other modules from depending on implementation details.- Service packages: business logic, often accepting interfaces for dependencies such as databases or API clients.
- Validation packages: check inputs early and return errors before continuing.
- Small focused packages: expose a limited API rather than making all implementation details public.
Use exported names deliberately. A package should expose the types and functions callers need, while keeping helper functions lowercase when callers should not rely on them.
Common Mistakes
Putting different packages in one directory
This is invalid:
// main.go
package main
// mylib.go
package mylib
Fix it by moving mylib.go into a mylib/ subdirectory.
Importing only the package name
This usually does not refer to a local package:
import "mylib"
Go treats it as an import path and looks for a package with that path, often among the standard library or configured dependencies. Import the full module-based path instead:
import "example.com/myapp/mylib"
Forgetting to initialize a module
Without go.mod, modern Go tooling has no local module path to use for imports. From the project root, run:
go mod init example.com/myapp
Trying to use lowercase identifiers from another package
This does not compile because newSomeType is unexported:
// package mylib
func newSomeType() {}
// package main
mylib.newSomeType()
Export it by starting the name with an uppercase letter:
func NewSomeType() {}
Expecting go build on a library to create a binary
A reusable package is not an executable. This command can succeed without producing a visible program file:
go build ./mylib
Build the main application to create an executable:
go build .
Running only one file when the package needs multiple files
Prefer this from the module root:
go run .
It builds the package in the current directory and follows its imports. go run main.go runs only the named file, which can be inconvenient when the program package has additional files.
Comparisons
| Concept | What it represents | Typical example |
|---|---|---|
| Package | A directory of Go source code with one package name | example.com/myapp/mylib |
| Module | A collection of related packages defined by go.mod | example.com/myapp |
package main | A special package that produces an executable when it has func main() | A CLI or web server entry point |
| Library package | Reusable code imported by other packages | mylib, store, service |
go run . | Builds and runs the current package | Run an application from its root |
go build . | Builds the current package | Create an executable for package main |
A directory normally corresponds to one package. A module can contain many directories and therefore many packages.
Cheat Sheet
One directory = one package name (excluding special test package cases)
One module = one go.mod file plus its packages
Initialize a module:
go mod init example.com/myapp
Recommended layout:
myapp/
├── go.mod
├── main.go # package main
└── mylib/
└── mylib.go # package mylib
Import a local package:
import "example.com/myapp/mylib"
Use an exported identifier:
item := mylib.SomeType{}
Export rule:
func Public() {} // usable by other packages
func private() {} // usable only inside this package
Useful commands from the module root:
go run .
go build .
go test ./...
go fmt ./...
A successful build of a non-main package may not create a binary file.
FAQ
Can two Go packages be in the same folder?
No. All ordinary .go files in one directory must use the same package declaration. Put each package in its own directory.
Why does Go say it cannot find my local package?
Usually the import path does not start with your module path, the package is in the wrong directory, or you have not created a go.mod file.
Does example.com/myapp need to exist online?
Not for local development. It is a module identifier. If you later publish the module, use the repository's real path, such as github.com/yourname/myapp.
Why did go build mylib.go not create an executable?
mylib.go declares a library package, not package main. Libraries are compiled for use by other packages and do not become standalone executables.
Should I run go run main.go or go run .?
Use go run . for a normal module-based application. It builds the package in the current directory and resolves its dependencies.
Why can I not call a lowercase function from another package?
Go uses capitalization for visibility. Only names beginning with an uppercase letter are exported outside their package.
Can a module contain multiple main packages?
Yes. Put each executable in a different directory, commonly under cmd/, because each directory is a separate package.
What should I name a Go package?
Use a short, lowercase name that describes its purpose, such as config, store, or mylib. Avoid generic names such as util unless the package has a genuinely focused purpose.
Mini Project
Description
Build a small command-line greeting application that imports a custom greetings package. This demonstrates the standard Go layout: a module root for the executable and a subdirectory for reusable code.
Goal
Create and run a program that calls an exported function from your own Go package.
Requirements
Create a Go module named example.com/greetingapp.
Create a greetings subdirectory containing a package greetings.
Add an exported Hello function that accepts a name and returns a greeting.
Import the package from main.go using the full module path.
Run the application with go run ..
Keep learning
Related questions
Are Go Maps Passed by Value or Reference?
Learn Go map parameter and return semantics: maps are passed by value, while copies share underlying data. Know when map pointers are useful.
Authentication for Go REST APIs: Sessions, Tokens, and Middleware
Learn practical authentication patterns for Go REST APIs, including password hashing, server sessions, bearer tokens, middleware, and security rules.
Automatic Build Versioning in Go: Embed Incrementing Build Numbers
Learn how to add automatic build versioning in Go using linker flags, build metadata, CI counters, and Git-based version values.