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:
- Single project & internal package
- Multiple projects & public shared package
- 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.
Once this is done, we should upload the project to GitHub.
For example, by using the following commands:
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.
And update the import instructions in the sample project main.go:
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