Writing Your First Micro-service API With Go

Adhitia Putra Herawan
5 min readApr 13, 2018

--

Introduction

Micro-services now-a-days has become most implemented technology on enterprise level. The concept of decoupled, independent and lite, are the reasons why most of companies choose it. The offers of High-Performance is tempting as well. And to supports the High-Performance features, we need to use the fast performance of programming language as well, and GO is one of the fast performance programming language for Micro-service platform. And go through this article, I will show you how to setup and create your first micro-service application using GO. This article will try to be as detail as it could be.

Go-Kit Framework

On this article, I will use Go-Kit as GO micro-service framework to help as creating the API easily.

Go is a great general-purpose language, but microservices require a certain amount of specialized support. RPC safety, system observability, infrastructure integration, even program design — Go kit fills in the gaps left by the standard library, and makes Go a first-class language for writing microservices in any organization.

So by using this Go-Kit framework, we are able to be more focus on our logic and leave the API process and communication to Go-Kit Framework. You need to download the Go-Kit framework first.

//go to your GOPATH location. Should be somewhere with "src" folder on the root
$ cd $GOPATH
//download the go-kit library from git-hub repository
$ go get github.com/go-kit/kit

So it will download all the needed library and put it in your $GOPATH location, and next we will use it as our external library.

Prepare Your Micro-service Project Structure

To make your coding process easier, I usually create the skeleton for the project as well. On this article, I will use my own skeleton architecture, but feel free to use your own. First I create GO Project with name : aph-go-service . And the skeleton for the project is like :

datastruct — all your json body request and response will be put here.

logging — this is the class to manage logging process on your application.

service — we put the business logic inside this folder.

transport — this will manage the communication process inside our micro-service.

main.go — the main class and we will call all the function from it.

Create Business Logic Function

Okay, so now we will first create our business logic function. As what previous section explained, we will create the business logic inside the service folder. So lets create service.go file inside it. For this article, lets make simple business logic process. Lets make “Hello World” function, that will return the string and con-cat it with input parameter. The input parameter is “name”, and the output should be “Hello, Name”.

package serviceimport (fmt "fmt")func HelloWorld(name string) string {    var helloOutput string    helloOutput = fmt.Sprintf("Hello, %s ", name)    return helloOutput}

Define Your Request and Response Body

So at the previous section, we have created the business logic process. Now we will create the transport package that will utilize the business logic function. But before we create the transport communication process, lets define our JSON Body Request and Body Response first. So we expect the request is as simple as just name, and the response has code, and the message it self. So lets create file go inside the datastruct folder, give name : datatstruct.go.

package datastructtype HelloWorldRequest struct {     NAME string `json:"name"`}type HelloWorldResponse struct {     STATUS  int    `json:"code"`     MESSAGE string `json:"message"`}

Create Transport Process

So at the previous section, we already created the business logic process and also the datastruct to store our JSON Body Request and Response. Now we will create the transport package that will utilize the business logic function and map the data into datastruct. First lets create go file inside transport folder with name : transport.go . First create interface that will have an implementation that call our business logic function.

package transportimport("context"
)
//create an interface named AphService that have a function that will have implementation that call our business logic functiontype AphService interface {
//The interface function. Has parameter context.Context
//and string that will keep our "NAME" input parameter
HelloWorldService(context.Context, string) string}//type implementation struct of the AphService interfacetype aphService struct{}

Okay, so next lets create the body or implementation of HelloWorldService interface.

//This function is the body of the interface.
//It call another function that will directly call the business //logic function
func (aphService) HelloWorldService(_ context.Context, name string) string{
//calling another function
return call_ServiceHelloWorld(name), ErrEmpty
}//this function call the business logic functionfunc call_ServiceHelloWorld(name string) string { messageResponse := service.HelloWorld(name)
//calling the function
return messageResponse //return the value}

Okay, so now we have the interface and also the body or the implementation. In order to make our function is callable as REST API function, next we have to create the endpoint, decodeRequest and encodeResponse inside the transport.go .

func makeHelloWorldEndpoint(aph AphService) endpoint.Endpoint {     return func(ctx context.Context, request interface{})    (interface{}, error) {     req := request.(datastruct.HelloWorldRequest)     v = aph.HelloWorldService(ctx, req.NAME)     return datastruct.HelloWorldResponse{200, v}, nil     }}func decodeHelloWorldRequest(_ context.Context, r *http.Request) (interface{}, error) {     var request datastruct.HelloWorldRequest     if err := json.NewDecoder(r.Body).Decode(&request); err != nil             {     return nil, err}return request, nil}func encodeResponse(_ context.Context, w http.ResponseWriter,   response interface{}) error {     return json.NewEncoder(w).Encode(response)}

Okay, so we have completed all needed function in order to make a end to end communication between request, response and our business logic. Lets create the handler that will define the API URL or PATH of our micro-service.

func RegisterHttpsServicesAndStartListener() {     aph := aphService{}     HelloWorldHandler := httptransport.NewServer(           makeHelloWorldEndpoint(aph),           decodeHelloWorldRequest,            encodeResponse,     )     //url path of our API service
http.Handle("/HelloWorld", HelloWorldHandler)
}

Finalize at main.go

Now we have everything settled. We just need to create the main function.

package mainimport ("aph-go-service/transport"_ "expvar""net/http""os""github.com/go-kit/kit/log")func main() {     logger := log.NewLogfmtLogger(os.Stdout)     transport.RegisterHttpsServicesAndStartListener()     port := os.Getenv("PORT")     if port == "" {         port = "8080"     }     logger.Log("listening-on", port)     if err := http.ListenAndServe(":"+port, nil); err != nil {          logger.Log("listen.error", err)     }}

Now all your GO micro-services are ready(actually only 1 :D). Just call using curl or you can use postman to test it. All the source code could be found at noydhiet git repo.

Next I will post on how to connect your API to database and return it in JSON format.

Happy coodding guuys.

--

--