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