Skip to content

Instantly share code, notes, and snippets.

@ayoubzulfiqar
Created September 5, 2023 06:12
Show Gist options
  • Save ayoubzulfiqar/9f1a34049332711fddd4d4b2bfd46096 to your computer and use it in GitHub Desktop.
Save ayoubzulfiqar/9f1a34049332711fddd4d4b2bfd46096 to your computer and use it in GitHub Desktop.
The Folder Structure for Every Golang Project

Go - The Ultimate Folder Structure

Organizing your Go (Golang) project's folder structure can help improve code readability, maintainability, and scalability. While there is no one-size-fits-all structure, here's a common folder structure for a Go project:

project-root/
    ├── cmd/
    │   ├── your-app-name/
    │   │   ├── main.go         # Application entry point
    │   │   └── ...             # Other application-specific files
    │   └── another-app/
    │       ├── main.go         # Another application entry point
    │       └── ...
    ├── internal/                # Private application and package code
    │   ├── config/
    │   │   ├── config.go       # Configuration logic
    │   │   └── ...
    │   ├── database/
    │   │   ├── database.go     # Database setup and access
    │   │   └── ...
    │   └── ...
    ├── pkg/                     # Public, reusable packages
    │   ├── mypackage/
    │   │   ├── mypackage.go    # Public package code
    │   │   └── ...
    │   └── ...
    ├── api/                     # API-related code (e.g., REST or gRPC)
    │   ├── handler/
    │   │   ├── handler.go      # HTTP request handlers
    │   │   └── ...
    │   ├── middleware/
    │   │   ├── middleware.go  # Middleware for HTTP requests
    │   │   └── ...
    │   └── ...
    ├── web/                     # Front-end web application assets
    │   ├── static/
    │   │   ├── css/
    │   │   ├── js/
    │   │   └── ...
    │   └── templates/
    │       ├── index.html
    │       └── ...
    ├── scripts/                 # Build, deployment, and maintenance scripts
    │   ├── build.sh
    │   ├── deploy.sh
    │   └── ...
    ├── configs/                 # Configuration files for different environments
    │   ├── development.yaml
    │   ├── production.yaml
    │   └── ...
    ├── tests/                   # Unit and integration tests
    │   ├── unit/
    │   │   ├── ...
    │   └── integration/
    │       ├── ...
    ├── docs/                    # Project documentation
    ├── .gitignore               # Gitignore file
    ├── go.mod                   # Go module file
    ├── go.sum                   # Go module dependencies file
    └── README.md                # Project README

Here's a brief explanation of the key directories:

  • cmd/: This directory contains application-specific entry points (usually one per application or service). It's where you start your application.

  • internal/: This directory holds private application and package code. Code in this directory is not meant to be used by other projects. It's a way to enforce access control within your project.

  • pkg/: This directory contains public, reusable packages that can be used by other projects. Code in this directory is meant to be imported by external projects.

  • api/: This directory typically holds HTTP or RPC API-related code, including request handlers and middleware.

  • web/: If your project includes a front-end web application, this is where you'd put your assets (CSS, JavaScript, templates, etc.).

  • scripts/: Contains scripts for building, deploying, or maintaining the project.

  • configs/: Configuration files for different environments (e.g., development, production) reside here.

  • tests/: Holds unit and integration tests for your code.

  • docs/: Project documentation, such as design documents or API documentation.

This is a general guideline, and you can adjust it to match the specific needs of your project. Additionally, you can consider using a project layout tool like "golang-standards/project-layout" as a reference to structure your Go project.

Other Possible

The folder structure for a Go project can vary depending on the size and complexity of the project, as well as personal or team preferences. Here are some alternative folder structures for Go projects:

  1. Flat Structure: In smaller projects, you might opt for a flat structure where all your Go source files reside in the project root directory. This approach is simple but may become hard to manage as the project grows.

    project-root/
        ├── main.go
        ├── handler.go
        ├── config.go
        ├── database.go
        ├── ...
        ├── static/
        ├── templates/
        ├── scripts/
        ├── configs/
        ├── tests/
        └── docs/
  2. Layered Structure: Organize your code into layers, such as "web," "api," and "data." This approach helps separate concerns.

    project-root/
        ├── main.go
        ├── web/
        │   ├── handler.go
        │   ├── static/
        │   ├── templates/
        ├── api/
        │   ├── routes.go
        │   ├── middleware/
        ├── data/
        │   ├── database.go
        │   ├── repository.go
        ├── configs/
        ├── tests/
        ├── docs/
  3. Domain-Driven Design (DDD): In larger applications, consider structuring your project based on domain-driven design principles. Each domain has its own directory.

    project-root/
        ├── cmd/
        │   ├── app1/
        │   ├── app2/
        ├── internal/
        │   ├── auth/
        │   │   ├── handler.go
        │   │   ├── service.go
        │   ├── orders/
        │   │   ├── handler.go
        │   │   ├── service.go
        │   ├── ...
        ├── pkg/
        │   ├── utility/
        │   │   ├── ...
        │   ├── ...
        ├── api/
        │   ├── app1/
        │   │   ├── ...
        │   ├── app2/
        │   │   ├── ...
        ├── web/
        │   ├── app1/
        │   │   ├── ...
        │   ├── app2/
        │   │   ├── ...
        ├── scripts/
        ├── configs/
        ├── tests/
        └── docs/
  4. Clean Architecture: You can adopt a clean architecture approach, which emphasizes a separation of concerns between different layers of your application.

    project-root/
        ├── cmd/
        │   ├── your-app/
        │   │   ├── main.go
        ├── internal/
        │   ├── app/
        │   │   ├── handler.go
        │   │   ├── service.go
        │   ├── domain/
        │   │   ├── model.go
        │   │   ├── repository.go
        ├── pkg/
        │   ├── utility/
        │   │   ├── ...
        ├── api/
        │   ├── ...
        ├── web/
        │   ├── ...
        ├── scripts/
        ├── configs/
        ├── tests/
        └── docs/
  5. Modular Structure: Organize your code into separate modules, each with its own directory structure. This approach can be useful when developing multiple independent components within a single project.

    project-root/
        ├── module1/
        │   ├── cmd/
        │   ├── internal/
        │   ├── pkg/
        │   ├── api/
        │   ├── web/
        │   ├── scripts/
        │   ├── configs/
        │   ├── tests/
        │   └── docs/
        ├── module2/
        │   ├── ...

Remember that the right folder structure depends on the specific needs of your project and your team's development practices. Choose a structure that helps maintain code organization, readability, and collaboration as your project evolves.

@iamSuva
Copy link

iamSuva commented Jul 8, 2024

It is a great explanation.Thank you for sharing

@dpi0
Copy link

dpi0 commented Aug 26, 2024

extremely useful!

@imanborumand
Copy link

thank you

@Shobhit-Nagpal
Copy link

oh dude, this is great!

@dangquyitt
Copy link

the case of DDD, how can we avoid circular imports when auth needs to import order and vice versa?

@ayoubzulfiqar
Copy link
Author

the case of DDD, how can we avoid circular imports when auth needs to import order and vice versa?

In Domain-Driven Design (DDD), circular dependencies between modules (like auth and order) can arise when different domains need to access each other's functionality. This is often a sign that the boundaries between the domains are not well defined or that one of the domains has too much coupling with the other.

Some Stratgies that i try if you really curious:

  1. Use Interfaces to Decouple
  2. Use Dependency Injection
  3. Event-Driven Approach (Event Sourcing or Domain Events)

and if you really wanna know more you can look into other principles that might be somthing that you are looking for

@rafaelfnaves
Copy link

This is great! Thanks.

@danielnicolae28
Copy link

The best explanation! Thank you!

@toluhikay
Copy link

Hey dude I love this

@bool3max
Copy link

bool3max commented Jun 5, 2025

Perhaps you should edit the "5. Modular Structure" example to include a go.mod file in each module folder to better illustrate that each folder is a separate Go module.

@BadalyanHarutyun
Copy link

BadalyanHarutyun commented Jun 13, 2025

Nice structure.

  1. is it good to have makefile?
  2. which way is much better for building this type of application go build cmd/your-app/main.go or go build cmd/your-app/
    Thanks

@ayoubzulfiqar
Copy link
Author

Nice structure.

  1. is it good to have makefile?
  2. which way is much better for building this type of application go build cmd/your-app/main.go or go build cmd/your-app/
    Thanks

yes actually using makefile is the better way to build and run the project main file

# Binary base name
BINARY_NAME=myapp

# Output directory
BUILD_DIR=bin

# Platforms to build for
PLATFORMS=\
	linux/amd64 \
	windows/amd64 \
	darwin/amd64

# Default target
.PHONY: all
all: build

# Build for current OS
.PHONY: build
build:
	go build -o $(BUILD_DIR)/$(BINARY_NAME) .

# Cross-compile for multiple platforms
.PHONY: build-all
build-all:
	@mkdir -p $(BUILD_DIR)
	@for platform in $(PLATFORMS); do \
		OS=$${platform%/*}; \
		ARCH=$${platform##*/}; \
		OUTPUT=$(BUILD_DIR)/$(BINARY_NAME)-$${OS}-$${ARCH}; \
		if [ "$${OS}" = "windows" ]; then OUTPUT=$${OUTPUT}.exe; fi; \
		echo "Building $${OUTPUT}..."; \
		GOOS=$${OS} GOARCH=$${ARCH} go build -o $${OUTPUT} . || exit 1; \
	done

# Run the application
.PHONY: run
run:
	go run .

# Test the application
.PHONY: test
test:
	go test ./...

# Format the code
.PHONY: fmt
fmt:
	go fmt ./...

# Lint the code (requires golangci-lint)
.PHONY: lint
lint:
	golangci-lint run

# Clean build files
.PHONY: clean
clean:
	rm -rf $(BUILD_DIR)

# Tidy modules
.PHONY: tidy
tidy:
	go mod tidy

Run in Terminal Like

make build   # Compiles the app
make run     # Runs the app
make test    # Runs tests
make fmt     # Formats code
make lint    # Runs linter (if installed)
make tidy    # Cleans up go.mod/go.sum
make clean   # Removes the binary
make build           # Build for current OS
make build-all       # Build for all platforms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment