Golang Project Structure Fundamentals and Organization

Author

Reads 1K

Workplace with modern laptop with program code on screen
Credit: pexels.com, Workplace with modern laptop with program code on screen

A well-structured Golang project is key to maintaining readability and scalability.

The Go programming language recommends organizing your project in a way that mirrors its dependencies, with the root directory containing the main package.

The project structure should be organized around packages, with each package containing related files and directories.

This approach helps keep your code organized and makes it easier to manage dependencies.

The main package, often named after the project, should contain the main function that serves as the entry point for the application.

This function is responsible for initializing the application and starting the main goroutine.

Project Structure Basics

A basic Go package has all its code in the project's root directory. This structure is ideal for simple projects requiring a single Go file.

In a basic package, the project consists of a single module, which consists of a single package. The package name matches the last path component of the module name.

Curious to learn more? Check out: Golang Go

Credit: youtube.com, The BEST Tool to Structure Golang Projects

A Go package can be split into multiple files, all residing within the same directory. All the files in the directory declare the same package name.

To rely on a package, users can import it in their Go code using the package name. For example, if the package is named "modname", users can import it with "import modname."

A well-organized folder structure is crucial for Go projects. It keeps different parts of the project, such as business logic, data access, and API handling, in their own folders.

Here are some key benefits of a good folder structure:

  • Separation of layers
  • Better organization
  • Reusability
  • Easier maintenance
  • Modularity

A layered structure is ideal for medium-sized projects. It promotes a clean architecture where handlers are solely responsible for managing requests, delegating business logic to services, and data access to repositories.

In a layered structure, each layer has its specific role, making the code easier to manage. This structure is particularly effective for projects with a clear separation of concerns.

Here are some common folder structures used in Golang projects:

  • Basic layout
  • Layered structure
  • Monorepo structure
  • Internal directory structure

A monorepo is a single repository that houses multiple services or libraries. This structure is commonly used in large organizations, allowing different projects to be developed and deployed independently while still living within a unified codebase.

Credit: youtube.com, This Is The BEST Way To Structure Your GO Projects

In a monorepo, each service is self-contained and operates independently, but they all reside within the same repository. This structure encourages sharing code and maintaining consistency across multiple services.

A small project can use the basic layout, where everything is in the project's root directory. This structure is ideal for simple projects requiring a single Go file.

For small projects, consider using the following layout:

* A couple of real-life examples of projects that use this layout are mkcert and flow.

The internal directory is used to make packages private. If a package is put inside an internal directory, other packages can't import it unless they share a common ancestor.

Here are some reasons to create packages judiciously:

  • You have some code that you want to reuse.
  • You want to isolate or enforce a boundary between the package code and the rest of your project.
  • You have some code that acts as a 'black box' and moving it to a standalone package will reduce cognitive overhead and make your codebase clearer overall.

A good project structure is essential for maintainability and scalability. It's not just about following a specific layout, but also about understanding the principles behind it.

By following these principles, you can create a project structure that works for you and your team. Remember, there's no one-size-fits-all solution, and the best structure will depend on your project's specific needs.

Best Practices

Credit: youtube.com, How I Structure New Projects In Golang

A good project structure is crucial for any GoLang project. A well-organized folder structure keeps different parts of your project in their own folders, making it easier for developers to focus on specific areas.

Here are some best practices to keep in mind:

  • Separate business logic, data access, and API handling into their own folders.
  • Keep constants, variables, and custom types close to the code they support.
  • Group utility functions that are related to each other and used in multiple places into a single reusable package.
  • Define methods for custom struct types directly below the struct declaration in the same file.

A good structure also encourages modular design, making it easier to add new features as your project grows. By following these best practices, you'll make your development process smoother and your project more maintainable.

Api

Api is a crucial part of any software development project. You can find OpenAPI/Swagger specs, JSON schema files, and protocol definition files in the /api directory.

These specs provide a clear understanding of the API's functionality and can be used for documentation and testing purposes. For example, you can find examples in the /api directory.

Having a well-organized api directory is essential for maintaining a clean and efficient codebase. It allows developers to easily access and manage the API's various components.

By following the best practices outlined in the api documentation, developers can ensure their API is scalable, secure, and easy to use.

Build

A diverse team of women engaged in a productive office meeting, working together with focus and dedication.
Credit: pexels.com, A diverse team of women engaged in a productive office meeting, working together with focus and dedication.

The build process is where the magic happens. Put your cloud package configurations and scripts in the /build/package directory.

Having a well-organized build process is crucial for success. Put your CI configurations and scripts in the /build/ci directory.

Some CI tools like Travis CI can be quite picky about the location of their config files. Try putting the config files in the /build/ci directory and linking them to the location where the CI tools expect them.

Organizing your build process in this way can save you a lot of time and headaches in the long run.

Docs

Designing clear and accessible documentation is crucial for any project.

You can find examples of user documents in the /docs directory.

Documentation is not just about generating godoc, it's also about creating design documents that are easy to understand.

The /docs directory is a great place to start when looking for examples of user documents.

Including design documents with your godoc generated documentation can help users get a better understanding of your project.

Here's an interesting read: Project Web Page Design

Tools

Diverse team working together at a modern office table with papers and technology.
Credit: pexels.com, Diverse team working together at a modern office table with papers and technology.

Tools are an essential part of any project, and Go makes it easy to create and manage them.

Supporting tools for a project can import code from the /pkg and /internal directories, as shown in the /tools directory for examples.

It's a good idea to keep your tools separate from your main code, but not strictly necessary in a repository that consists only of commands.

Users can install these programs as follows: A common convention is placing all commands in a repository into a cmd directory, which is very useful in a mixed repository with both commands and importable packages.

Examples

Examples are a crucial part of any application or public library. They help users understand how to use the code and provide a starting point for their own projects.

You can find examples in the /examples directory. This is a great resource for developers who want to see how the code works in practice.

A diverse group of colleagues working together in a modern office setting.
Credit: pexels.com, A diverse group of colleagues working together in a modern office setting.

Examples for your applications and/or public libraries are essential for publicizing your work and making it easier for others to use. They also serve as a proof of concept, demonstrating the capabilities of your code.

The /examples directory is the place to look for these examples. It's a treasure trove of code snippets and complete applications that you can use as a reference.

By using examples, you can make your code more accessible and user-friendly. This is especially important for public libraries, where examples can help users understand how to use the code and get started with their own projects.

Examples are a key part of the development process, and they can be found in the /examples directory.

Dirs to Avoid

In Go, creating a directory creates a new package, which can lead to unnecessary complexity.

You shouldn't create new directories just to organize your .go files, as this can make your code harder to manage.

This is especially true if you're new to Go, where the package structure is a crucial part of the language. Don't create a directory unless you have a specific reason to create a new package.

A different take: Go vs Golang

Feature-Based Folder Structure

Credit: youtube.com, This Folder Structure Makes Me 100% More Productive

Feature-Based Folder Structure is a great way to organize your code, especially for large applications. This approach treats each feature or functionality as a separate unit, with all related code residing within that feature's directory.

Each feature encapsulates its own logic, models, and layers, minimizing unwanted dependencies. This makes it easier to maintain and enhance the codebase for specific functionalities.

Large applications with multiple distinct features are best suited for this structure. Examples include user management, product catalogs, or order processing, which can be logically separated.

Some benefits of this approach include high cohesion, where related code for each feature is grouped together, making it easier to maintain and enhance. It also promotes a focus on business needs, aligning closely with business requirements and making it intuitive for development teams.

Here are some characteristics of Feature-Based Folder Structure:

  • Encapsulation: Each feature encapsulates its own logic, models, and layers.
  • Scalability: The structure can easily grow as new features are added.
  • Focus on Business Needs: Since the organization revolves around features, it aligns closely with business requirements.
  • High Cohesion: Related code for each feature is grouped together.

Feature teams organized around feature ownership can also benefit from this structure, as it enhances collaboration and accountability.

Two young professionals brainstorming at work in a modern office setting.
Credit: pexels.com, Two young professionals brainstorming at work in a modern office setting.

Keeping related items together is a fundamental principle in organizing your code. This approach helps maintain a clean and efficient structure, making it easier to navigate and understand.

In Go, it's recommended to keep constants, variables, custom types, and utility functions close to the code they support, in the same .go file or package. This way, you can easily find and update related code.

You can group utility functions that are related to each other and used in multiple places into a single reusable package. This also helps reduce code duplication and makes your codebase more maintainable.

  1. Keep constants and variables close to the code they support.
  2. Group utility functions into a single reusable package.
  3. Define methods for custom struct types directly below the struct declaration in the same .go file.
  4. Define all routing rules together in a single function or .go file.

By keeping related items together, you can create a more cohesive and scalable codebase. This approach also promotes encapsulation, which is essential for maintaining a clean and efficient structure.

Design Patterns and Architectures

In a GoLang project, a well-structured design pattern can make all the difference in maintaining a clean and efficient codebase. One such pattern is the Onion Architecture, which emphasizes the separation of concerns by organizing code into concentric circles.

Credit: youtube.com, Repository Pattern in Go - How to Structure your Projects

This layered approach is structured in concentric circles, with the innermost layer representing the core domain and the outer layers representing the application’s interfaces and infrastructure. By separating the core domain logic from external dependencies, you can promote maintainability and testability.

Onion Architecture is particularly suitable for applications with intricate business rules that require a clear separation of concerns. It's also ideal for long-term projects expected to evolve over time, allowing developers to adapt to changes in business requirements without significant rewrites.

Here are some key characteristics of Onion Architecture:

  • Layered Approach: The innermost layer represents the core domain and the outer layers represent the application’s interfaces and infrastructure.
  • Dependency Inversion: The core domain logic remains independent of external frameworks and technologies.
  • Separation of Concerns: Each layer has distinct responsibilities, helping to isolate changes and minimize side effects.
  • Focus on Business Logic: The core business logic stays at the center.
  • Testability: Easier to write unit tests for the domain and application layers.

By incorporating Onion Architecture into your GoLang project, you can create a robust and maintainable codebase that's well-suited for complex business domains and long-term projects.

Onion Architecture

Onion Architecture emphasizes the separation of concerns by organizing code into concentric circles (or layers) around a central core. The innermost layer represents the business logic and domain model.

This architecture is structured in concentric circles, with the innermost layer representing the core domain and the outer layers representing the application's interfaces and infrastructure. The core domain logic remains independent of external frameworks and technologies, promoting maintainability and testability.

Credit: youtube.com, Onion Architecture - Software Design Patterns Explained

Each layer has distinct responsibilities, helping to isolate changes and minimize side effects. The core business logic stays at the center, allowing the application to evolve without impacting external dependencies.

This architecture is suitable for applications with intricate business rules that require a clear separation of concerns. It's ideal for long-term projects expected to evolve over time, enabling developers to adapt to changes in business requirements without significant rewrites.

Here are some key benefits of Onion Architecture:

This architecture is particularly useful for teams with clear roles, where different teams are responsible for various layers of the application. It's also ideal for projects where the business logic must remain decoupled from external systems like databases, APIs, or UI frameworks.

Common Architecture

The Common Architecture is a great choice for simpler projects or scenarios where speed of development and ease of understanding are prioritized. It's perfect for smaller applications or projects where complexity is manageable, and strict separation of concerns may be overkill.

Credit: youtube.com, Architectural Patterns

One of the key benefits of Common Architecture is its simplicity. It organizes code without excessive complexity, making it easier to understand the project layout for newcomers. This is especially useful for individual developers who prefer a simple, less structured environment for building applications.

Here are some scenarios where Common Architecture shines:

By choosing Common Architecture, you can focus on developing your application without getting bogged down by strict architectural guidelines. This makes it an excellent choice for projects where speed of development and ease of understanding are top priorities.

Project Size and Complexity

Project size and complexity play a significant role in determining the structure of your Go codebase. There's no one-size-fits-all approach, and what works for one project might not work for another.

For smaller projects, you can use the supporting packages layout, where supporting packages live within an internal directory in the project root, and your main package files and other project assets continue to live in the root directory.

Credit: youtube.com, The Only Go Project Structure You'll Ever Need

In contrast, larger projects benefit from the server project layout. This layout is ideal when your project has a lot of non-.go assets, such as template files, SQL migrations, and Makefiles. It's also suitable when your project contains more than one main package.

Here are some key differences between the supporting packages layout and the server project layout:

Remember, the key is to choose a layout that fits your project's specific needs, and don't be afraid to experiment and adapt as your project grows and evolves.

Small Projects with Support

Small projects with support can be a bit more complex, but still manageable. For these types of projects, it's best to use the supporting packages layout, where internal packages live within an internal directory in the project root.

This layout is useful when you need to break out some code into separate packages. You can see this pattern in use in projects like mkcert and flow.

Diverse team collaborating on a software project in a contemporary office setting.
Credit: pexels.com, Diverse team collaborating on a software project in a contemporary office setting.

One advantage of this layout is that it keeps your main package files and other project assets in the root directory, where they're easy to find. This can make it simpler to navigate and work with your project.

For example, mkcert uses this layout to keep its main package files and other project assets in the root directory, while breaking out its internal packages into a separate directory.

A unique perspective: Golang Test Main

Larger Projects

Larger projects require a more organized structure to manage complexity. This is especially true when dealing with non-.go assets like template files, SQL migrations, and tool configurations.

If your project will have a lot of these assets, it's best to use the server project layout. This layout is ideal for projects with multiple main packages.

For example, if you're building a web application and a CLI tool, you'll want to use the server project layout. Your executable main package files will live in subdirectories under a cmd directory.

Credit: youtube.com, Architecting LARGE software projects.

The rest of your Go packages will live in an internal directory. This keeps your code organized and easy to navigate.

Here's a summary of the benefits of the server project layout for larger projects:

  • Separates executable main package files from the rest of your Go packages
  • Keeps non-.go assets like template files and SQL migrations in the root of the project directory
  • Helps manage complexity in larger projects

Evolution and Organization

Letting your project structure evolve naturally is key to maintaining a clean and organized Go codebase. This involves not deciding on a directory structure or file organization upfront, but rather allowing it to develop as you write your code.

The approach to take is to start with a standard project layout as your high-level "skeleton". This provides a solid foundation for your project, but don't worry too much about the details at this stage.

As development progresses, your code will guide the creation of new files and packages, rather than the other way around.

Jeannie Larson

Senior Assigning Editor

Jeannie Larson is a seasoned Assigning Editor with a keen eye for compelling content. With a passion for storytelling, she has curated articles on a wide range of topics, from technology to lifestyle. Jeannie's expertise lies in assigning and editing articles that resonate with diverse audiences.

Love What You Read? Stay Updated!

Join our community for insights, tips, and more.