project-layout icon indicating copy to clipboard operation
project-layout copied to clipboard

Go project sturcture question

Open SofiaTa opened this issue 7 years ago • 10 comments

Hi,

I've created this question https://stackoverflow.com/questions/47788850/go-project-structure-best-practise in stack overflow and I wonder if the repo author can give is insight.

Thanks, Sofia

SofiaTa avatar Dec 13 '17 09:12 SofiaTa

Feel free to adopt any structure that makes sense for you and your project. The project layout represents a set of patterns you can choose to adopt, so don't feel that it's the only true way :)

Having said that here are my two comments:

  1. The 'src' folder:

Some Go projects do have a 'src' folder, but it usually happens when the devs came from the Java world where it's a common pattern. If you can help yourself try not to adopt this Java pattern. You really don't want your Go code or Go projects to look like Java :-)

  1. The 'main.go' application file:

Keep it as small as possible. Import the application packages and invoke them in the main function. Here's an example: https://github.com/heptio/ark/blob/master/cmd/ark/main.go

  1. The application cmd name:

There should be another subdirectory in the 'cmd' folder unless you want your application to be called 'cmd' :-)

For example, the path to main.go should look like this: .../myproj/src/cmd/myapp/main.go If you adopt the first recommendation it would look like this: .../myproj/cmd/myapp/main.go

  1. The 'utils' code:

Put your 'utils' code in the 'pkg' directory.

.../myproj/src/pkg/utils If you adopt the first recommendation it would look like this: .../myproj/pkg/utils

Note that having a 'utils' package is considered an anti-pattern because it's not descriptive enough. Other blob posts cover the exact whys. This project layout tries to stay high level and un-opinionated in terms of the actual package structure.

P.S. The blog post, https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2 , that goes along with the repo provides additional references about the project structure others are using (e.g., "Analysis of the Top 1000 Go Repositories"). Take a look and it might give you more ideas.

kcq avatar Feb 01 '18 02:02 kcq

Hey @kcq, thanks for putting this together! It's helped me put together my current (and future) projects!

Just a quick question, where would I put my models? I've been told many times that I shouldn't have a models package as the grouping should be by responsibility.

So, would I be creating something like internal/user/user.go for the User model for example?

bt avatar Mar 06 '18 03:03 bt

This project layout is intentionally generic and it doesn't try to impose this level of structure :-)

Depending on how you want to control visibility of your models (if you want to have models :)) they may go in your-project/pkg/your-lib/your-models (if the models are used by one or more of your apps or if they can be reused externally by 3rd parties) or your-project/internal/pkg/your-private-lib/your-models (if the models are meant to be shared by multiple apps in your project) or your-project/internal/app/your-app-name/your-models (if the models are meant to be used only by a specific app in your project)

Take a look at this blog post if you are looking for something more opinionated: https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1 Warning... it'll try to convince you that having models is not a good idea for Go code :-) You can combine the ideas from that blog post with this generic project layout. Just use one of the location I mentioned above as the root for the packages you define. For example, you might have your-project/pkg/domain/user.go .

kcq avatar Mar 11 '18 01:03 kcq

If I create directories within internal such as database with a db.go file within there. Should the package of db.go be 'internal' or 'database'?

Digi1mpulse avatar Apr 06 '18 18:04 Digi1mpulse

@Digi1mpulse The structure should probably be something like internal/database/db.go, which would put it in the database package, as the package name is always the most specific folder that the file is in, though that db.go could probably be either more specific, or split into more specific file(s) since it will be in it's own package. Just my $.02

coreydaley avatar Apr 14 '18 02:04 coreydaley

Hi, in which directory better to add the migration sql? What do you think about misc/migrations?

kveselkov avatar Jul 19 '18 07:07 kveselkov

@KosToZyB I usually have a database directory in the root package with the following content:

  • if I have to support multiple database engines then I have a subfolder per engine (eg. mysql, postgres, etc)
  • then I have a Dockerfile which can be used for local development and execute the migrations itself
  • on the same level I have a migrations directory with the migrations in it

Alternatively you can use an etc directory for things like configurations, etc.

Hope this helps

sagikazarmark avatar Aug 14 '18 21:08 sagikazarmark

Hi, in which directory better to add the code that about web application? example router. what about add router in root directory?

TGhoul avatar Sep 29 '18 02:09 TGhoul

@KosToZyB it depends on how much structure you want to adopt for your project.

If you want to use the pkg or internal/pkg layout patterns then you can have a db or database package/lib directory in one of those two locations (in /pkg if you are ok for 3rd parties importing your code or /internal/pkg if it's a piece of code reusable by multiple components/apps in your project).

If you are in the "I don't want to use pkg layout pattern" camp then a sub-directory in the top level db or database directory is a good place.

If your migration sql is sql files (that get loaded at run time) and not Go code with sql statements then you can put your migrations in the /configs/sql directory. This is my preferred approach, which I usually combine with a dedicated/separate app that performs the actual migration. Another potential option is a top level /sql directory. This is a good option too because it follows the /api directory pattern especially if you intend to embed those resources in your binary.

kcq avatar Sep 29 '18 16:09 kcq

@TGhoul your web application is likely going to be set of packages, which means you can put those packages either in the /pkg directory (if you don't mind if others import your code) or the /internal/pkg directory if you want to keep your web app code private.

Take a look at this GopherCon 2018 video by Kat Zien (How Do You Structure Your Go Apps): https://www.youtube.com/watch?v=oL6JBUk6tj0

The video will help you with slicing your web app into packages using the hexagon architecture approach and the pkg layout pattern.

kcq avatar Sep 29 '18 16:09 kcq