How to Structure a Go Project from Scratch: A Step‑by‑Step Guide

This tutorial walks new Go developers through naming a project, initializing a module, creating the essential directory layout and files, adding tests, and building a simple CLI while emphasizing Go's KISS and YAGNI principles.

21CTO
21CTO
21CTO
How to Structure a Go Project from Scratch: A Step‑by‑Step Guide

New Go developers may face many confusions: how to organize code, which directories to create, how deep the nesting should be, where to place files, how to handle tests and test data, and whether to follow existing templates or generators.

If you have experience with Rails or Django, you might see people creating empty directory trees and trying to fit growing Go code into them, which can feel puzzling.

Let’s start a new project by building a Go API client for Shodan, the search engine for internet‑connected devices.

First, choose a project name that will also serve as the Go module name on GitHub. For this exercise we name it godan as the Shodan Go SDK/API. godan Create a directory with the same name: mkdir godan Enter the directory:

cd godan

Creating Go Module (Package)

Initialize the godan directory as a Go module using go mod init and name it github.com/qba73/godan: go mod init github.com/qba73/godan This creates a go.mod file:

module github.com/qba73/godan

go 1.23.4

The first line declares the module name; the second specifies the Go version.

Next, we don’t need extra directories yet—just create two files, one for code and one for tests:

touch godan_test.go
touch godan.go

The file names match the module name. Add package declarations: package godan (in godan.go) package godan_test (in godan_test.go)

The test package imports the godan package, allowing us to test exported functions.

Running tree shows the module structure:

tree
.
├── go.mod
├── godan.go
└── godan_test.go

1 directory, 3 files

This minimal setup is enough to start test‑driven development while applying the KISS and YAGNI principles.

Adding CLI

When we decide to add a command‑line interface, create a cmd directory and a main.go file inside it: mkdir cmd Place main.go in the new directory:

tree
.
├── cmd
│   └── main.go
├── go.mod
├── godan.go
└── godan_test.go

2 directories, 4 files
main.go

is the entry point of the Go application; it imports the godan package and calls its exported functions:

package main

import "github.com/qba73/godan"

func main() {
    // Call your app entry point here.
}

This is all that the godan package needs. If a CLI is required, the cmd/main.go handles it.

All design decisions start and end with packaging. – B. Kennedy

We don’t need fancy generators—just an organic design approach.

Key differences in the Go mindset:

Keep it simple

Focus on readability

Make things easy to understand

Defer design decisions until the right moment, when you see functions that could become separate packages or files.

Building a Go application is like cultivating a garden.

Start with a few small flowers; over weeks add more, arrange them on shelves, and only add infrastructure like greenhouses when truly needed.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

TestingBackend DevelopmentGoproject-structuremodule initialization
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.