1

We recently started using Go for new microservices. Each microservice is a Go module, and we manage them as a monorepo:

/
  services/
    s1/
      go.mod
      main.go
    s2/
      go.mod
      main.go

This works fine, but now we need to share some code between s1 and s2 - some structs used by both services, a function that uploads to S3, etc.

What's the correct way of managing this situation? Ideally, I'd have a common directory at the repo root (sibling of services) and put the common code there - but how will Go take the code from there when compiling s1 and s2?

noamtm
  • 12,435
  • 15
  • 71
  • 107

1 Answers1

4

I think what you're asking is really just a variation of "How to structure Go application to produce multiple binaries?".

You would move your go.mod to the top-level directory rename, so that you have this layout:

.
├── common
│   └── common.go
├── go.mod
└── services
    ├── s1
    │   └── main.go
    └── s2
        └── main.go

And a go.mod that starts with something like:

module mymodule

If common/common.go looks like this:

package common

func CommonFunction() string {
    return "This is a common function"
}

Then in services/s1/main.go, you can import the common module:

package main

import (
        "mymodule/common"
        "fmt"
)

func main() {
        res := common.CommonFunction()
        fmt.Println(res)
}

And you would build the s1 service like this:

go build ./services/s1

Building s2 would be similar:

go build ./services/s2

You would typically have a top-level Makefile to automate building of the multiple services.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • This looks great, thanks. I will give it a try and if it does what I need I'll accept. – noamtm Apr 19 '23 at 08:00
  • What if `s1` needs dependencies that are not needed by `s2`? A single `go.mod` means they will both get it, and the docker image will be larger. – noamtm Apr 19 '23 at 11:26
  • 1
    I'm not sure that's true. I think the Go linker is smart enough to not include unnecessary dependencies in the compiled binary. I'm not 100% sure, so if your existing project has those characteristics, try this structure and see what impact it has on the final sizes. – larsks Apr 19 '23 at 12:02