Wednesday, January 29, 2020

GO Shared Library




Many projects are based on microservices architecture, and a GO based development. Such a development method usually generates a need for a common shared code among the microservices.
In this post we will review the GO shared library concerns including:

  1. Single project & internal package
  2. Multiple projects & public shared package
  3. Multiple projects & internal shared package


1. Single Project & Internal Package


Let's start with a simple project, which includes a package.
Following the How to Write Go Code article, we get the following files structure:






The project includes the main.go file, which calls to a function from the greet package.


package main
import (
   "fmt"   "github.com/alonana/go-sample-project/greet")

func main() {
   fmt.Printf("Hello, %v\n", greet.RandomGreet())
}



And the greeting.go in the greet package includes the shared code.


package greet
import "math/rand"
var names = []string{"Mister", "Lady", "Alice", "Bob"}

func RandomGreet() string {
   return names[rand.Intn(len(names))]
}



In addition, the project is using GO modules, so a go.mod file is included:


module github.com/alonana/go-sample-project
go 1.12



Some points that should be handled for a shared package:

  • An exposed API should use upper case names. For example, the RandomGreet is exposed, while the names array is internal to the greet package.
  • All the files in the same folder should have the same package name.


2. Multiple Projects & Public Shared Package


As we progress in our development, we find that the greet package should be shared among multiple microservices. Since we want to avoid code duplication, we create a separate project for the greet package, and use it in each project.

Let first create the greet shared project, using the following files structure:




The greeting.go remains the same, however, as this is a new project, we need to create its own go.mod file.


module github.com/alonana/greet
go 1.12


Once this is done, we should upload the project to GitHub.
For example, by using the following commands:


git init
git add go.mod
git add greeting.go
git commit -m "First commit"
git remote add origin https://github.com/alonana/greet.git
git push -u origin master


Next, we update the sample project. We delete the greeting.go from the project. and update the go.mod to use the public version of the greet package.


module github.com/alonana/go-sample-project
go 1.12
require github.com/alonana/greet v0.0.0-20200129080101-0619d8064721


And update the import instructions in the sample project main.go:


package main
import "fmt"import "github.com/alonana/greet"
func main() {
   fmt.Printf("Hello, %v\n", greet.RandomGreet())
}



3. Multiple Projects & Internal Shared Package


A shared package through the github is nice, but it includes a overhead. 
After each update to the shared package we should update the GitHub, and update the projects, that are using the package, to import the new version. That's good if the package is stable, and is seldom updated. However, if the shared package if often updated, this overhead is cumbersome.

To avoid this, we can import the package directly by a relative path. 
This is done by updating the go.mod of the sample project:


module github.com/alonana/go-sample-project
go 1.12
require github.com/alonana/greet v0.0.0-00010101000000-000000000000
replace github.com/alonana/greet => ../greet


This assumes that both the sample project and the shared package project reside in the same parent folder. In case it is not so, usage of a absolute path is also possible.



Final Notes


In this post we've examined methods for using a shared package.

I myself have used the replace method in the go.mod file. This method is great. Any update to the shared package files immediately affects the using projects. I strongly recommend using this method.

Notice that each of these methods require different handling for a related docker image creation. For example, the replace method requires copying of the shared library into the source folder of the built project.

No comments:

Post a Comment