Search code examples
gomicroservicesdirectory-structure

Golang microservice project structure


I'm at an initial stage of creating a microservice application in Go, but due to the way that the import paths and directories are handled I'm not quite sure what's best way to structure the project files.

Normally, the project would look something like this in Java:

|-- gateway_microservice
   |-- src
   |-- docker
|-- config_microservice
   |-- src
   |-- docker
|-- recommendation_microservice
   |-- src
   |-- docker
|-- users_microservice
   |-- src
   |-- docker

Now if I do it the same way in Go, the import paths become somewhat cumbersome:

import (
       "fmt" 
       "github.com/user/myproject/gateway_microservice/src/package1"
       "github.com/user/myproject/gateway_microservice/src/package2"
)

Additionally, I hear that the idiomatic way is to put all main.go files in a separate cmd directory, which adds to the confusion. Would it look something like this:

|-- cmd
   |-- gateway_microservice
      |-- main.go
   |-- config_microservice
      |-- main.go
   |-- recommendation_microservice
      |-- main.go
   |-- users_microservice
      |-- main.go
|-- gateway_microservice
   |-- src
   |-- docker
|-- config_microservice
   |-- src
   |-- docker
|-- recommendation_microservice
   |-- src
   |-- docker
|-- users_microservice
   |-- src
   |-- docker

What is the 'correct' or idiomatic way of structuring a project like this in Go?


Solution

  • The other answer here advocates putting each microservice into its own repository. There may be valid reasons for splitting things up that way, but there may be equally valid reasons from wanting to keep everything in one repository as well (it really depends on your project / circumstances)

    If you want all the code in one repository, you can- you just need to follow Go's package rules. (this is a good read: https://golang.org/doc/code.html#Workspaces)

    If you have a mix of commands and libraries, the directory structure you proposed in your question comes close, but you probably don't need the src directories in there. Here's an example of how a directory structure within a repo with libraries and commands might look:

    lib1/
    -- some.go
    -- source.go
    lib2/
    -- more.go
    -- source.go
    cmd/
    -- microservice1/
       -- main.go
    -- microservice2/
       -- anothermain.go
    

    To use this repository, you would clone it inside a Go workspace on your system (see the link I shared above). Assuming your repository lives in github.com/mybiz/project, and your GOPATH was ~/go, the workspace would look as follows:

    ~/go/src/github.com/mybiz/
      -- project/
         <clone repo in here>
    

    The file cmd/microservice1/main.go would include the library lib1 via a path it expects it in relative to $GOPATH/src as follows:

    import "github.com/mybiz/project/lib1"
    

    Now, your code has access to the exported symbols in that package using the package name declared in the files under lib1... usually just:

    package lib1
    

    In cmd/microservice1/main.go, with the import above, you could use lib1 symbols as follows:

    lib1.CallMe()
    

    I hope that helps clear up how Go's directory structure works.