### 2025.05.23 Λ 16:04
![[gopher_points_to_dir.jpg]]
Recently, I started learning Go ([[Go Language Series]]) on my own. As someone who designs and prototypes for a living, I've found that the best way to learn something new is by working on a personal project—one that forces you to understand the intricacies of the thing you're trying to learn.
So you can imagine my reaction when it came time to structure a repository. Like, how am I even supposed to format it?
## The Map
Based on all the research I've done, I've found this to be the best way to structure a Go repository.
```
myapp/ ← 1. repo root
├── .gitignore ← 2. Git ignore rules
├── LICENSE
├── README.md ← 3. overview, build/run instructions
├── go.mod ← 4. module definition
├── go.sum ← 5. dependency checksums
│
├── cmd/ ← 6. entry‐point applications
│ ├── myapp/ ← 7. main “myapp” binary
│ │ └── main.go
│ └── myappctl/ ← 8. auxiliary CLI tool
│ └── main.go
│
├── internal/ ← 9. private application code
│ ├── server/
│ └── datastore/
│
├── pkg/ ← 10. public libraries for external use
│ └── api/
│
├── configs/ ← 11. configuration file templates or examples
│ └── config.yaml
│
├── scripts/ ← 12. helper scripts (build, lint, release)
│ └── ci-check.sh
│
├── build/ ← 13. packaging and CI/CD manifests
│ ├── Dockerfile
│ └── github-ci.yml
│
└── docs/ ← 14. design docs, ADRs, swagger/openapi specs
└── architecture.md
```
## The Breakdown
Let's cut to the chase. Here's the reasoning behind this directory layout:
1. **Repo Root**: This is the top-level directory for your app, the root (`/`). We house all other files and directories here. This is also where you'd initialize your Go repository using the command: `go mod init myapp`, with `myapp` being your root directory.
2. **.gitignore**: This file always goes into the root of any `.git`-initialized repository. Here, we specify files or directories we don't want Git to track—things like sensitive data, IDE configuration files, etc.
3. **README.md**: That information you see at the bottom of a repository on GitHub or GitLab? That's this file. I know, it's basic—but to all the newbies out there, we all started where you are.
4. **go.mod**: This is where Go tracks all the external modules you use throughout your code. You update this file using the command `go mod tidy`.
5. **go.sum**: Managed by Go itself, this file keeps track of all module fingerprints to ensure nobody tampers with them. It prevents downloading modified or malicious code. Don't touch this manually.
6. **cmd/**: As stated, this is the entry point of the program. It houses `main.go` and other main-like Go files.
7. **cmd/myapp/**: Second-level directory inside `cmd`. It contains the actual `main.go` file, as well as binaries created by compiling `main.go`.
8. **cmd/myappctl/**: Optional directory for auxiliary tools related to `myapp`.
9. **internal/**: This is where all backend code is stored and where we'll spend most of our time. I place the internal workings of the code into logical modules here to keep things organized and avoid spaghetti code. You'd further subdivide this as needed.
10. **pkg/**: Here, you'd place general-purpose, reusable code that isn't necessarily specific to `myapp`, but can be imported if needed. Think utility templates, standalone functions, etc.—not application-specific logic like what's inside `internal`.
11. **configs/**: I have a personal bias towards config files. I really like them, just as I like `.env` files and Helm's `values.yaml`. Basically, you'd store all key-value pairs or YAML configurations here to customize the Go program further.
12. **scripts/**: Shell scripts or Python scripts that speed up deployment or initialize parts of your code infrastructure. Essentially, DevOps stuff.
13. **build/**: Where the Dockerfile lives. I've seen `gitlab-ci.yaml` files placed here before, though they're also commonly found in the repository's root directory.
14. **docs/**: Documentation for `myapp` resides here—diagrams, guides, etc. I've also seen `INSTALL.md` here. The sky's the limit.
Although not set in stone, this layout is a solid template for structuring a Go repository.
## Quick Tip
Initially, it wasn't clear to me how to import multiple modules into something like `main.go`. But when I learned how, it reminded me of Python. Let me explain further with actual code.
Say my `main.go` file is located here: `/yara_engine/cmd/yara_engine/main.go`, and I want to import a module located at `/yara_engine/internal/server/server.go`. If you initialized the root directory using the command `go mod init yara_engine`, here's how you'd correctly import a module:
```go
package main
import (
"yara_engine/internal/server" // <- Notice this.
)
func main() {
server.Start() // Starts the server
}
```
Notice how `server.go` doesn't appear explicitly—only its directory is referenced. Go automatically picks up `server.go` from there and makes its functions available. Pretty cool, right?
Also, if you add another module in the import statement and run `go mod tidy`, your `go.mod` file will be updated accordingly.
Anyway, enough of that. You have what you need. Go conquer.
--Another seed in the garden.
**If you need any help or want to get in contact with me, Click [[🌱 The Syntax Garden]] where I have my contact details.**