Question

How to Create and Import Custom Packages in Go

goimportpackage

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 main can 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.mod file 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 package declaration.
  • 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).

Take Quiz

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:

  1. It reads go.mod and finds the module path: example.com/myapp.
  2. It loads the root package, which is package main.
  3. It sees the import example.com/myapp/mylib.
  4. It maps that import path to the local mylib directory inside the module.
  5. It compiles the mylib package.
  6. It compiles main, which calls mylib.Greeting("Sam").
  7. Greeting returns "Hello, Sam".
  8. fmt.Println prints 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/httpapi or handlers.
  • Database access: Keep queries and repository code in a store or database package.
  • Business rules: Place pricing, permissions, or order logic in a service package.
  • Reusable utilities: Put focused helpers, such as date formatting or validation, in a small package.
  • Command-line tools: Keep package main small and place command logic in separate packages.
  • Shared types: Define domain types such as User, Order, or Invoice near 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.

Take Quiz

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 a package 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

ConceptWhat it representsTypical example
PackageA directory of Go source code with one package nameexample.com/myapp/mylib
ModuleA collection of related packages defined by go.modexample.com/myapp
package mainA special package that produces an executable when it has func main()A CLI or web server entry point
Library packageReusable code imported by other packagesmylib, store, service
go run .Builds and runs the current packageRun an application from its root
go build .Builds the current packageCreate an executable for package main

A directory normally corresponds to one package. A module can contain many directories and therefore many packages.

Take Quiz

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.

Take Quiz

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 ..

Take Quiz

Keep learning

Related questions

View more