30

I have some confusion regarding Golang directory structure.

Base on the book The Way to Go by Ivo Balbaert, project code should be placed into src, and recommends the following directory structure.

    ├──src/
    |  ├──main.go
    |  ├──say/
    |  |  ├──say.go
    |  |  ├──say_test.go
    ├──bin/
    |  ├──say
    └──pkg/
       └──linux_amd64/
          └──say.a

but I found that many packages in github.com, have no src directory.

For example:

https://github.com/facebookgo/grace

https://github.com/astaxie/beego

So, I don't know whether src directory is needed.

I have some project, their have inter-dependency. They are managed in a private GitLab repository.

How can I organized them?

Matthew Rankin
  • 457,139
  • 39
  • 126
  • 163
goosman.lei
  • 386
  • 1
  • 3
  • 7
  • 10
    What your book is probably describing is the tree of the GOPATH directory. –  Oct 09 '17 at 12:34
  • Thank you very much, I'm foolish – goosman.lei Oct 09 '17 at 12:41
  • Probably late but another great example for go project boilerplate is qiangxue's starter kit - https://github.com/qiangxue/golang-restful-starter-kit –  Jan 26 '18 at 19:42

5 Answers5

30

This article by Ben Johnson has guided me on this when I was starting with Go.

It's generally good to start with something like this (assuming you are inside your project directory like $GOPATH/src/myproject:

├──cmd/ -- this is where you compose several packages in to main package
|  ├──foo -- an example would be `foo`
|  |  ├──main.go
├──pkg/ -- this is where put your reusable packages 
|  ├──pkg1 -- reusable package 1
|  ├──pkg2 -- reusable package 2
├──otherpackage1
|  ├── ...
├──otherpackage2
|  ├── ...

You can have a look at this example from go-kit for this kind of project structure.

Sometimes it will depend on your needs. On our workflow, we are using a hot code reload tool called fresh, so we needed to put the main.go on the project root so that the tool can detect all the file changes and rebuild the source code.

├──app/
|  ├──app.go
├──model/ -- 
|  ├──model.go
├──store
|  ├──store.go
├──main.go -- this is where the app starts
├──...

On the app.go package, I have something like func Run() error which starts the application. On the main.go, I am just calling the function:

...
func main(){
    log.Fatal(app.Run())
}
Matthew Rankin
  • 457,139
  • 39
  • 126
  • 163
stevenferrer
  • 2,504
  • 1
  • 22
  • 33
11

Now there are new ways to organize Go projects. The GitHub golang-standards repository says:

This is a basic layout for Go application projects. It represents the most common directory structure with a number of small enhancements along with several supporting directories common to any real world application.

This project layout is intentionally generic and it doesn't try to impose a specific Go package structure.

Or you can follow this slides:

$GOPATH/
    src/
        github.com/user/repo/
            mypkg/
                mysrc1.go
                mysrc2.go
            cmd/mycmd/
                main.go
    bin/
        mycmd
Matthew Rankin
  • 457,139
  • 39
  • 126
  • 163
Radonirina Maminiaina
  • 6,958
  • 4
  • 33
  • 60
  • 8
    Although the repo contains a couple of interesting points, it seems to be _not_ an official guidance by golang. In other words, it is just "yet another" opinion on the topic, so I would not position it as a "new way" as "new way" sounds like an ultimate guidance that overrules existing ones. – The Ancient Oct 04 '18 at 09:24
6

Here is another project layout sample Simple Go project layout with modules

├── LICENSE
├── README.md
├── config.go
├── go.mod
├── go.sum
├── clientlib
│   ├── lib.go
│   └── lib_test.go
├── cmd
│   ├── modlib-client
│   │   └── main.go
│   └── modlib-server
│       └── main.go
├── internal
│   └── auth
│       ├── auth.go
│       └── auth_test.go
└── serverlib
    └── lib.go

Some answer points out the go standard layout, however, there is one issue this is not a standard Go project layout by Russ Cox

There are two problems with this GitHub repo:

  • it claims to host Go standards and does not, in the sense that these are in no way official standards
  • the project-layout standard it puts forth is far too complex and not a standard

Regarding "why not tell us the standard Go project layout and we'll update the doc?", that only addresses point 2. If there really were standards, they would be in the main Go project doc tree. The standard for project layout would also be a lot shorter. I appreciate your trying to provide a useful resource, but calling it 'golang-standards' is claiming more than it is.

But for the record, the minimal standard layout for an importable Go repo is really:

  • Put a LICENSE file in your root
  • Put a go.mod file in your root
  • Put Go code in your repo, in the root or organized into a directory tree as you see fit

That's it. That's the "standard".


Update at 11/30/2021

Here are a summary from How to structure Go code

  • Before we start
    • doc.go file puts the general description of the package
    • Readme file a general overview of this project
    • When you have more documentation to provide put them into the docs folder
    • For linting use golangci-lint. Enable all linters that seem to be reasonable for your project
  • The flat structure (single package)
    courses/
      main.go
      server.go
      user_profile.go
      lesson.go
      course.go
    
    • When to create a new package?
      • When you have more than one way of starting your application
      • When you want to extract more detailed implementation
      • When you started to add a common prefix to closely related things
  • Modularisation
    • Organising by kind
.
├── handlers
│   ├── course.go
│   ├── lecture.go
│   ├── profile.go
│   └── user.go
├── main.go
├── models
│   ├── course.go
│   ├── lecture.go
│   └── user.go
├── repositories
│   ├── course.go
│   ├── lecture.go
│   └── user.go
├── services
│   ├── course.go
│   └── user.go
└── utils
    └── stings.go
  • Organising by components
.
├── course
│   ├── httphandler.go
│   ├── model.go
│   ├── repository.go
│   └── service.go
├── main.go
└── profile
    ├── httphandler.go
    ├── model.go
    ├── repository.go
    └── service.go
  • Clean Architecture
    • You have 4 layers of your application or module (depending on how big your codebase is): Domain, Application, Ports, Adapters. In some sources, names may differ.
zangw
  • 43,869
  • 19
  • 177
  • 214
3

The src directory is not needed and in fact a lot of public repositories do not use this structure.

There is a few different way of organizing your project. If you plan on having your project used by an other repository, like lib. I would recommend using a cmd struct something like this. This would also be the recommended way of doing it if there would be more then one way of starting the application. (multipliable main.go files)

├──cmd/
|  ├──(application name)
|  |  ├──main.go
└──say/
   ├──say.go
   └──say_test.go

Otherwise for example if it is a standalone application. You can place the main.go in the root of the repository.

bin and pkg you can keep in the root and add this to .gitignore. (assuming you are using git)

Icy Creature
  • 1,875
  • 2
  • 28
  • 53
  • bin and pkg should be in the root of `GOPATH`, they shouldn't be in the project directory at all, just like src. – Adrian Oct 09 '17 at 14:05
  • The golang standards `golang-standards/project-layout` on [github](https://github.com/golang-standards/project-layout) agrees on the `src` directory. – tristram Jul 09 '20 at 13:59
  • 1
    @Compree You mean disagrees? There's an explicit section named [Directories You Shouldn't Have](https://github.com/golang-standards/project-layout#directories-you-shouldnt-have) which includes `/src` – Seraf Apr 21 '21 at 12:02
  • Yes, Seraf, you are right. My unclear comment was that src is unnecessary. – tristram May 24 '21 at 11:31
3

The book describes the directory structure after checkout. It would have been helpful if the book included the .git directory.

$GOPATH/src is required for imports to work.

    ├──src/
    |  ├──.git
    |  |  ├──...
    |  ├──main.go
    |  ├──say/
    |  |  ├──say.go
    |  |  ├──say_test.go
    ├──bin/
    |  ├──say
    └──pkg/
       └──linux_amd64/
          └──say.a

In practice, main.go would actually be in a path that reflects the remote git repository, for instance

.   
├── bin
│   └── say
├── pkg
│   └── linux_amd64
│       └── github.com
│           └── pschultz
│               └── hello-world
│                   └── say.a
└── src
    └── github.com
        └── pschultz
            └── hello-world
                ├── .git
                │   └── ...
                ├── main.go
                └── say
                    ├── say.go
                    └── say_test.go
Peter
  • 29,454
  • 5
  • 48
  • 60